Azerotcore-wotlk
Unit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Affero General Public License as published by the
6  * Free Software Foundation; either version 3 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "AccountMgr.h"
19 #include "ArenaSpectator.h"
20 #include "Battlefield.h"
21 #include "BattlefieldMgr.h"
22 #include "Battleground.h"
23 #include "CellImpl.h"
24 #include "Chat.h"
25 #include "ChatTextBuilder.h"
26 #include "Common.h"
27 #include "ConditionMgr.h"
28 #include "Creature.h"
29 #include "CreatureAI.h"
30 #include "CreatureAIImpl.h"
31 #include "CreatureGroups.h"
32 #include "DisableMgr.h"
33 #include "DynamicVisibility.h"
34 #include "Formulas.h"
35 #include "GridNotifiersImpl.h"
36 #include "Group.h"
37 #include "InstanceSaveMgr.h"
38 #include "InstanceScript.h"
39 #include "Log.h"
40 #include "MapMgr.h"
41 #include "MoveSpline.h"
42 #include "MoveSplineInit.h"
43 #include "ObjectAccessor.h"
44 #include "ObjectMgr.h"
45 #include "Opcodes.h"
46 #include "OutdoorPvP.h"
47 #include "PassiveAI.h"
48 #include "Pet.h"
49 #include "PetAI.h"
50 #include "Player.h"
51 #include "QuestDef.h"
52 #include "ReputationMgr.h"
53 #include "Spell.h"
54 #include "SpellAuraEffects.h"
55 #include "SpellAuras.h"
56 #include "SpellInfo.h"
57 #include "SpellMgr.h"
59 #include "TemporarySummon.h"
60 #include "Totem.h"
61 #include "TotemAI.h"
62 #include "Transport.h"
63 #include "Unit.h"
64 #include "UpdateFieldFlags.h"
65 #include "Util.h"
66 #include "Vehicle.h"
67 #include "World.h"
68 #include "WorldPacket.h"
69 #include "WorldSession.h"
70 #include <math.h>
71 
72 #ifdef ELUNA
73 #include "LuaEngine.h"
74 #include "ElunaEventMgr.h"
75 #endif
76 
78 {
79  2.5f, // MOVE_WALK
80  7.0f, // MOVE_RUN
81  4.5f, // MOVE_RUN_BACK
82  4.722222f, // MOVE_SWIM
83  2.5f, // MOVE_SWIM_BACK
84  3.141594f, // MOVE_TURN_RATE
85  7.0f, // MOVE_FLIGHT
86  4.5f, // MOVE_FLIGHT_BACK
87  3.14f // MOVE_PITCH_RATE
88 };
89 
91 {
92  2.5f, // MOVE_WALK
93  7.0f, // MOVE_RUN
94  4.5f, // MOVE_RUN_BACK
95  4.722222f, // MOVE_SWIM
96  2.5f, // MOVE_SWIM_BACK
97  3.141594f, // MOVE_TURN_RATE
98  7.0f, // MOVE_FLIGHT
99  4.5f, // MOVE_FLIGHT_BACK
100  3.14f // MOVE_PITCH_RATE
101 };
102 
103 // Used for prepare can/can`t triggr aura
104 static bool InitTriggerAuraData();
105 // Define can trigger auras
107 // Define can't trigger auras (need for disable second trigger)
109 // Triggered always, even from triggered spells
111 // Prepare lists
113 
114 DamageInfo::DamageInfo(Unit* _attacker, Unit* _victim, uint32 _damage, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage)
115  : m_attacker(_attacker), m_victim(_victim), m_damage(_damage), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask),
116  m_damageType(_damageType), m_attackType(BASE_ATTACK), m_cleanDamage(cleanDamage)
117 {
118  m_absorb = 0;
119  m_resist = 0;
120  m_block = 0;
121 }
122 
124  : m_attacker(dmgInfo.attacker), m_victim(dmgInfo.target), m_damage(dmgInfo.damage), m_spellInfo(nullptr), m_schoolMask(SpellSchoolMask(dmgInfo.damageSchoolMask)),
125  m_damageType(DIRECT_DAMAGE), m_attackType(dmgInfo.attackType), m_absorb(dmgInfo.absorb), m_resist(dmgInfo.resist), m_block(dmgInfo.blocked_amount),
126  m_cleanDamage(dmgInfo.cleanDamage)
127 {
128 }
129 
130 DamageInfo::DamageInfo(SpellNonMeleeDamage const& spellNonMeleeDamage, DamageEffectType damageType)
131  : m_attacker(spellNonMeleeDamage.attacker), m_victim(spellNonMeleeDamage.target), m_damage(spellNonMeleeDamage.damage),
132  m_spellInfo(spellNonMeleeDamage.spellInfo), m_schoolMask(SpellSchoolMask(spellNonMeleeDamage.schoolMask)), m_damageType(damageType),
133  m_absorb(spellNonMeleeDamage.absorb), m_resist(spellNonMeleeDamage.resist), m_block(spellNonMeleeDamage.blocked),
134  m_cleanDamage(spellNonMeleeDamage.cleanDamage)
135 {
136 }
137 
139 {
140  amount = std::min(amount, int32(GetDamage()));
141  m_damage += amount;
142 }
143 
145 {
146  amount = std::min(amount, GetDamage());
147  m_absorb += amount;
148  m_damage -= amount;
149 }
150 
152 {
153  amount = std::min(amount, GetDamage());
154  m_resist += amount;
155  m_damage -= amount;
156 }
157 
159 {
160  amount = std::min(amount, GetDamage());
161  m_block += amount;
162  m_damage -= amount;
163 }
164 
166 {
168 }
169 
170 ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell const* spell, DamageInfo* damageInfo, HealInfo* healInfo, SpellInfo const* triggeredByAuraSpell, int8 procAuraEffectIndex)
171  : _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask),
172  _hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo), _triggeredByAuraSpell(triggeredByAuraSpell), _procAuraEffectIndex(procAuraEffectIndex)
173 {
174 }
175 
177 {
178  if (_spell)
179  return _spell->GetSpellInfo();
180 
181  if (_damageInfo)
182  return _damageInfo->GetSpellInfo();
183 
184  if (_healInfo)
185  return _healInfo->GetSpellInfo();
186 
187  return nullptr;
188 }
189 
190 // we can disable this warning for this since it only
191 // causes undefined behavior when passed to the base class constructor
192 #ifdef _MSC_VER
193 #pragma warning(disable:4355)
194 #endif
195 Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
196  m_movedByPlayer(nullptr),
197  m_lastSanctuaryTime(0),
198  IsAIEnabled(false),
199  NeedChangeAI(false),
200  m_ControlledByPlayer(false),
201  m_CreatedByPlayer(false),
202  movespline(new Movement::MoveSpline()),
203  i_AI(nullptr),
204  i_disabledAI(nullptr),
205  m_realRace(0),
206  m_race(0),
207  m_AutoRepeatFirstCast(false),
208  m_procDeep(0),
209  m_removedAurasCount(0),
210  i_motionMaster(new MotionMaster(this)),
211  m_regenTimer(0),
212  m_ThreatMgr(this),
213  m_vehicle(nullptr),
214  m_vehicleKit(nullptr),
215  m_unitTypeMask(UNIT_MASK_NONE),
216  m_HostileRefMgr(this),
217  m_comboTarget(nullptr)
218 {
219 #ifdef _MSC_VER
220 #pragma warning(default:4355)
221 #endif
224 
226 
233 
234  m_extraAttacks = 0;
235  m_canDualWield = false;
236 
237  m_rootTimes = 0;
238 
239  m_state = 0;
241 
242  for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i)
243  m_currentSpells[i] = nullptr;
244 
245  for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
246  m_SummonSlot[i].Clear();
247 
248  for (uint8 i = 0; i < MAX_GAMEOBJECT_SLOT; ++i)
249  m_ObjectSlot[i].Clear();
250 
252 
253  m_interruptMask = 0;
254  m_transform = 0;
255  m_canModifyStats = false;
256 
257  for (uint8 i = 0; i < MAX_SPELL_IMMUNITY; ++i)
258  m_spellImmune[i].clear();
259 
260  for (uint8 i = 0; i < UNIT_MOD_END; ++i)
261  {
262  m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
263  m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
265  m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
266  }
267  // implement 50% base damage from offhand
269 
270  for (uint8 i = 0; i < MAX_ATTACK; ++i)
271  {
274  }
275 
276  for (uint8 i = 0; i < MAX_STATS; ++i)
277  m_createStats[i] = 0.0f;
278 
279  m_attacking = nullptr;
280  m_modMeleeHitChance = 0.0f;
281  m_modRangedHitChance = 0.0f;
282  m_modSpellHitChance = 0.0f;
284 
285  m_CombatTimer = 0;
286  m_lastManaUse = 0;
287 
288  for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
289  m_threatModifier[i] = 1.0f;
290 
291  for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
292  m_speed_rate[i] = 1.0f;
293 
294  m_charmInfo = nullptr;
295 
297 
298  // remove aurastates allowing special moves
299  for (uint8 i = 0; i < MAX_REACTIVE; ++i)
300  m_reactiveTimer[i] = 0;
301 
302  m_cleanupDone = false;
303  m_duringRemoveFromWorld = false;
304 
306 
307  m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
312 
313  m_applyResilience = false;
314  _instantCast = false;
315 
316  _lastLiquid = nullptr;
317 
318  _oldFactionId = 0;
319 }
320 
322 // Methods of class GlobalCooldownMgr
324 {
325  GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
326  return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, World::GetGameTimeMS()) < itr->second.duration;
327 }
328 
330 {
332 }
333 
335 {
336  m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
337 }
338 
340 // Methods of class Unit
342 {
343  // set current spells as deletable
344  for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i)
345  if (m_currentSpells[i])
346  {
348  m_currentSpells[i] = nullptr;
349  }
350 
352 
353  delete i_motionMaster;
354  delete m_charmInfo;
355  delete movespline;
356 
359  ASSERT(m_attackers.empty());
360 
361  // pussywizard: clear m_sharedVision along with back references
362  if (!m_sharedVision.empty())
363  {
364  LOG_INFO("misc", "Unit::~Unit (B1)");
365  do
366  {
367  LOG_INFO("misc", "Unit::~Unit (B2)");
368  Player* p = *(m_sharedVision.begin());
369  p->m_isInSharedVisionOf.erase(this);
370  m_sharedVision.erase(p);
371  } while (!m_sharedVision.empty());
372  }
373 
374  ASSERT(m_Controlled.empty());
375  ASSERT(m_appliedAuras.empty());
376  ASSERT(m_ownedAuras.empty());
377  ASSERT(m_removedAuras.empty());
378  ASSERT(m_gameObj.empty());
379  ASSERT(m_dynObj.empty());
380 
381  if (m_movedByPlayer && m_movedByPlayer != this)
382  LOG_INFO("misc", "Unit::~Unit (A1)");
383 
385 }
386 
387 void Unit::Update(uint32 p_time)
388 {
389 #ifdef ELUNA
390  elunaEvents->Update(p_time);
391 #endif
392  // WARNING! Order of execution here is important, do not change.
393  // Spells must be processed with event system BEFORE they go to _UpdateSpells.
394  // Or else we may have some SPELL_STATE_FINISHED spells stalled in pointers, that is bad.
395  m_Events.Update(p_time);
396 
397  if (!IsInWorld())
398  return;
399 
400  // pussywizard:
401  if (GetTypeId() != TYPEID_PLAYER || (!ToPlayer()->IsBeingTeleported() && !bRequestForcedVisibilityUpdate))
402  {
404  {
405  if (m_delayed_unit_relocation_timer <= p_time)
406  {
408  //ExecuteDelayedUnitRelocationEvent();
409  FindMap()->i_objectsForDelayedVisibility.insert(this);
410  }
411  else
413  }
415  {
416  if (m_delayed_unit_ai_notify_timer <= p_time)
417  {
420  }
421  else
423  }
424  }
425 
426  _UpdateSpells( p_time );
427 
428  if (CanHaveThreatList() && getThreatMgr().isNeedUpdateToClient(p_time))
430 
431  // update combat timer only for players and pets (only pets with PetAI)
433  {
434  // Check UNIT_STATE_MELEE_ATTACKING or UNIT_STATE_CHASE (without UNIT_STATE_FOLLOW in this case) so pets can reach far away
435  // targets without stopping half way there and running off.
436  // These flags are reset after target dies or another command is given.
437  if (m_HostileRefMgr.isEmpty())
438  {
439  // m_CombatTimer set at aura start and it will be freeze until aura removing
440  if (m_CombatTimer <= p_time)
441  ClearInCombat();
442  else
443  m_CombatTimer -= p_time;
444  }
445  }
446 
447  // not implemented before 3.0.2
448  // xinef: if attack time > 0, reduce by diff
449  // if on next update, attack time < 0 assume player didnt attack - set to 0
450  bool suspendAttackTimer = false;
452  {
453  for (Spell* spell : m_currentSpells)
454  {
455  if (spell)
456  {
457  if (spell->GetSpellInfo()->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS))
458  {
459  suspendAttackTimer = true;
460  break;
461  }
462  }
463  }
464  }
465 
466  if (!suspendAttackTimer)
467  {
468  if (int32 base_attack = getAttackTimer(BASE_ATTACK))
469  {
470  setAttackTimer(BASE_ATTACK, base_attack > 0 ? base_attack - (int32) p_time : 0);
471  }
472 
473  if (int32 off_attack = getAttackTimer(OFF_ATTACK))
474  {
475  setAttackTimer(OFF_ATTACK, off_attack > 0 ? off_attack - (int32) p_time : 0);
476  }
477  }
478 
479  if (int32 ranged_attack = getAttackTimer(RANGED_ATTACK))
480  {
481  setAttackTimer(RANGED_ATTACK, ranged_attack > 0 ? ranged_attack - (int32) p_time : 0);
482  }
483 
484  // update abilities available only for fraction of time
485  UpdateReactives(p_time);
486 
487  if (IsAlive())
488  {
492  }
493 
494  UpdateSplineMovement(p_time);
495  GetMotionMaster()->UpdateMotion(p_time);
496 }
497 
499 {
500  if (Player const* player = ToPlayer())
501  return player->GetWeaponForAttack(OFF_ATTACK, true);
502 
503  return CanDualWield();
504 }
505 
506 void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed)
507 {
508  Movement::MoveSplineInit init(this);
509  init.MoveTo(x, y, z);
510  init.SetVelocity(speed);
511  init.Launch();
512 }
513 
514 void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 TransitTime, SplineFlags sf)
515 {
516  WorldPacket data(SMSG_MONSTER_MOVE, 1 + 12 + 4 + 1 + 4 + 4 + 4 + 12 + GetPackGUID().size());
517  data << GetPackGUID();
518 
519  data << uint8(0); // new in 3.1
522  data << uint8(0);
523  data << uint32(sf);
524  data << TransitTime; // Time in between points
525  data << uint32(1); // 1 single waypoint
526  data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
527 
528  SendMessageToSet(&data, true);
529 }
530 
532 {
533 public:
534  SplineHandler(Unit* unit) : _unit(unit) { }
535 
537  {
541  {
543  }
544 
545  return true;
546  }
547 
548 private:
550 };
551 
553 {
554  if (movespline->Finalized())
555  return;
556 
557  // xinef: process movementinform
558  // this code cant be placed inside EscortMovementGenerator, because we cant delete active MoveGen while it is updated
559  SplineHandler handler(this);
560  movespline->updateState(t_diff, handler);
561  // Xinef: Spline was cleared by StopMoving, return
562  if (!movespline->Initialized())
563  {
564  DisableSpline();
565  return;
566  }
567 
568  bool arrived = movespline->Finalized();
569 
570  if (arrived)
571  {
572  DisableSpline();
573 
576  }
577 
578  // pussywizard: update always! not every 400ms, because movement generators need the actual position
579  //m_movesplineTimer.Update(t_diff);
580  //if (m_movesplineTimer.Passed() || arrived)
582 }
583 
585 {
586  //static uint32 const positionUpdateDelay = 400;
587 
588  //m_movesplineTimer.Reset(positionUpdateDelay);
590 
591  if (movespline->onTransport)
592  {
594  pos.m_positionX = loc.x;
595  pos.m_positionY = loc.y;
596  pos.m_positionZ = loc.z;
597  pos.m_orientation = loc.orientation;
598 
599  if (TransportBase* transport = GetDirectTransport())
600  transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
601  }
602 
603  // Xinef: this is bullcrap, if we had spline running update orientation along with position
604  //if (HasUnitState(UNIT_STATE_CANNOT_TURN))
605  // loc.orientation = GetOrientation();
606 
607  if (GetTypeId() == TYPEID_PLAYER)
608  UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
609  else
610  ToCreature()->SetPosition(loc.x, loc.y, loc.z, loc.orientation);
611 }
612 
614 {
617 }
618 
620 {
622  m_attackTimer[type] = std::min(m_attackTimer[type] + time, time);
623 }
624 
625 bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
626 {
627  if (!obj || !IsInMap(obj) || !InSamePhase(obj))
628  return false;
629 
630  float dx = GetPositionX() - obj->GetPositionX();
631  float dy = GetPositionY() - obj->GetPositionY();
632  float dz = GetPositionZ() - obj->GetPositionZ();
633  float distsq = dx * dx + dy * dy + dz * dz;
634 
635  float sizefactor = GetCombatReach() + obj->GetCombatReach();
636  float maxdist = dist2compare + sizefactor;
637 
638  return distsq < maxdist * maxdist;
639 }
640 
641 bool Unit::IsWithinMeleeRange(const Unit* obj, float dist) const
642 {
643  if (!obj || !IsInMap(obj) || !InSamePhase(obj))
644  return false;
645 
646  float dx = GetPositionX() - obj->GetPositionX();
647  float dy = GetPositionY() - obj->GetPositionY();
648  float dz = GetPositionZ() - obj->GetPositionZ();
649  float distsq = dx * dx + dy * dy + dz * dz;
650 
651  float maxdist = dist + GetMeleeRange(obj);
652 
653  return distsq < maxdist * maxdist;
654 }
655 
656 float Unit::GetMeleeRange(Unit const* target) const
657 {
658  float range = GetCombatReach() + target->GetCombatReach() + 4.0f / 3.0f;
659  return std::max(range, NOMINAL_MELEE_RANGE);
660 }
661 
662 bool Unit::IsWithinRange(Unit const* obj, float dist) const
663 {
664  if (!obj || !IsInMap(obj) || !InSamePhase(obj))
665  {
666  return false;
667  }
668 
669  auto dx = GetPositionX() - obj->GetPositionX();
670  auto dy = GetPositionY() - obj->GetPositionY();
671  auto dz = GetPositionZ() - obj->GetPositionZ();
672  auto distsq = dx * dx + dy * dy + dz * dz;
673 
674  return distsq <= dist * dist;
675 }
676 
677 bool Unit::GetRandomContactPoint(const Unit* obj, float& x, float& y, float& z, bool force) const
678 {
679  float combat_reach = GetCombatReach();
680  if (combat_reach < 0.1f) // sometimes bugged for players
681  combat_reach = DEFAULT_COMBAT_REACH;
682 
683  uint32 attacker_number = getAttackers().size();
684  if (attacker_number > 0)
685  --attacker_number;
686  const Creature* c = obj->ToCreature();
687  if (c)
688  if (c->isWorldBoss() || c->IsDungeonBoss() || (obj->IsPet() && const_cast<Unit*>(obj)->ToPet()->isControlled()))
689  attacker_number = 0; // pussywizard: pets and bosses just come to target from their angle
690 
691  GetNearPoint(obj, x, y, z, isMoving() ? (obj->GetCombatReach() > 7.75f ? obj->GetCombatReach() - 7.5f : 0.25f) : obj->GetCombatReach(), 0.0f,
692  GetAngle(obj) + (attacker_number ? (static_cast<float>(M_PI / 2) - static_cast<float>(M_PI) * (float)rand_norm()) * float(attacker_number) / combat_reach * 0.3f : 0));
693 
694  // pussywizard
695  if (fabs(this->GetPositionZ() - z) > this->GetCollisionHeight() || !IsWithinLOS(x, y, z))
696  {
697  x = this->GetPositionX();
698  y = this->GetPositionY();
699  z = this->GetPositionZ();
700  obj->UpdateAllowedPositionZ(x, y, z);
701  }
702  float maxDist = GetMeleeRange(obj);
703  if (GetExactDistSq(x, y, z) >= maxDist * maxDist)
704  {
705  if (force)
706  {
707  x = this->GetPositionX();
708  y = this->GetPositionY();
709  z = this->GetPositionZ();
710  return true;
711  }
712  return false;
713  }
714  return true;
715 }
716 
718 {
719  m_interruptMask = 0;
720  for (AuraApplicationList::const_iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i)
721  m_interruptMask |= (*i)->GetBase()->GetSpellInfo()->AuraInterruptFlags;
722 
724  if (spell->getState() == SPELL_STATE_CASTING)
725  m_interruptMask |= spell->m_spellInfo->ChannelInterruptFlags;
726 }
727 
728 bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const
729 {
730  if (!HasAuraType(auraType))
731  return false;
732  AuraEffectList const& auras = GetAuraEffectsByType(auraType);
733  for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
734  if (SpellInfo const* iterSpellProto = (*itr)->GetSpellInfo())
735  if (iterSpellProto->SpellFamilyName == familyName && iterSpellProto->SpellFamilyFlags[0] & familyFlags)
736  return true;
737  return false;
738 }
739 
741 {
742  AuraEffectList const& auras = GetAuraEffectsByType(type);
743  for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
744  if ((!excludeAura || excludeAura != (*itr)->GetSpellInfo()->Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction
745  ((*itr)->GetSpellInfo()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_TAKE_DAMAGE))
746  return true;
747  return false;
748 }
749 
750 bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) const
751 {
752  uint32 excludeAura = 0;
753  if (Spell* currentChanneledSpell = excludeCasterChannel ? excludeCasterChannel->GetCurrentSpell(CURRENT_CHANNELED_SPELL) : nullptr)
754  excludeAura = currentChanneledSpell->GetSpellInfo()->Id; //Avoid self interrupt of channeled Crowd Control spells like Seduction
755 
761 }
762 
763 void Unit::DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb)
764 {
765  if (!victim || !victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
766  {
767  if (absorb)
768  *absorb += damage;
769  damage = 0;
770  }
771 }
772 
773 uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss, bool /*allowGM*/)
774 {
775  // Xinef: initialize damage done for rage calculations
776  // Xinef: its rare to modify damage in hooks, however training dummy's sets damage to 0
777  uint32 rage_damage = damage + ((cleanDamage != nullptr) ? cleanDamage->absorbed_damage : 0);
778 
779  //if (attacker)
780  {
781  if (victim->IsAIEnabled)
782  victim->GetAI()->DamageTaken(attacker, damage, damagetype, damageSchoolMask);
783 
784  if (attacker && attacker->IsAIEnabled)
785  attacker->GetAI()->DamageDealt(victim, damage, damagetype);
786  }
787 
788  // Hook for OnDamage Event
789  sScriptMgr->OnDamage(attacker, victim, damage);
790 
791  if (victim->GetTypeId() == TYPEID_PLAYER && attacker != victim)
792  {
793  // Signal to pets that their owner was attacked
794  Pet* pet = victim->ToPlayer()->GetPet();
795 
796  if (pet && pet->IsAlive())
797  pet->AI()->OwnerAttackedBy(attacker);
798  }
799 
800  //Dont deal damage to unit if .cheat god is enable.
801  if (victim->GetTypeId() == TYPEID_PLAYER)
802  {
803  if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD))
804  {
805  return 0;
806  }
807  }
808 
809  // Signal the pet it was attacked so the AI can respond if needed
810  if (victim->GetTypeId() == TYPEID_UNIT && attacker != victim && victim->IsPet() && victim->IsAlive())
811  victim->ToPet()->AI()->AttackedBy(attacker);
812 
813  if (damagetype != NODAMAGE)
814  {
815  // interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
816  if (spellProto)
817  {
820  }
821  else
823 
824  // We're going to call functions which can modify content of the list during iteration over it's elements
825  // Let's copy the list so we can prevent iterator invalidation
827  // copy damage to casters of this aura
828  for (AuraEffectList::iterator i = vCopyDamageCopy.begin(); i != vCopyDamageCopy.end(); ++i)
829  {
830  // Check if aura was removed during iteration - we don't need to work on such auras
831  if (!((*i)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
832  continue;
833  // check damage school mask
834  if (((*i)->GetMiscValue() & damageSchoolMask) == 0)
835  continue;
836 
837  Unit* shareDamageTarget = (*i)->GetCaster();
838  if (!shareDamageTarget)
839  continue;
840  SpellInfo const* spell = (*i)->GetSpellInfo();
841 
842  uint32 shareDamage = CalculatePct(damage, (*i)->GetAmount());
843 
844  uint32 shareAbsorb = 0;
845  uint32 shareResist = 0;
846 
847  if (shareDamageTarget->IsImmunedToDamageOrSchool(damageSchoolMask))
848  {
849  shareAbsorb = shareDamage;
850  shareDamage = 0;
851  }
852  else
853  {
854  DamageInfo sharedDamageInfo(attacker, shareDamageTarget, shareDamage, spellProto, damageSchoolMask, damagetype);
855  Unit::CalcAbsorbResist(sharedDamageInfo, true);
856  shareAbsorb = sharedDamageInfo.GetAbsorb();
857  shareResist = sharedDamageInfo.GetResist();
858  shareDamage = sharedDamageInfo.GetDamage();
859  Unit::DealDamageMods(shareDamageTarget, shareDamage, &shareAbsorb);
860  }
861 
862  if (attacker && shareDamageTarget->GetTypeId() == TYPEID_PLAYER)
863  attacker->SendSpellNonMeleeDamageLog(shareDamageTarget, spell, shareDamage, damageSchoolMask, shareAbsorb, shareResist, damagetype == DIRECT_DAMAGE, 0, false);
864 
865  Unit::DealDamage(attacker, shareDamageTarget, shareDamage, cleanDamage, NODAMAGE, damageSchoolMask, spellProto, false);
866  }
867  }
868 
869  // Rage from Damage made (only from direct weapon damage)
870  if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->getPowerType() == POWER_RAGE)
871  {
872  uint32 weaponSpeedHitFactor;
873 
874  switch (cleanDamage->attackType)
875  {
876  case BASE_ATTACK:
877  case OFF_ATTACK:
878  {
879  weaponSpeedHitFactor = uint32(attacker->GetAttackTime(cleanDamage->attackType) / 1000.0f * (cleanDamage->attackType == BASE_ATTACK ? 3.5f : 1.75f));
880  if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
881  weaponSpeedHitFactor *= 2;
882 
883  attacker->RewardRage(rage_damage, weaponSpeedHitFactor, true);
884  break;
885  }
886  case RANGED_ATTACK:
887  break;
888  default:
889  break;
890  }
891  }
892 
893  if (!damage)
894  {
895  // Rage from absorbed damage
896  if (cleanDamage && cleanDamage->absorbed_damage)
897  {
898  if (victim->getPowerType() == POWER_RAGE)
899  victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
900 
901  if (attacker && attacker->getPowerType() == POWER_RAGE )
902  attacker->RewardRage(cleanDamage->absorbed_damage, 0, true);
903  }
904 
905  return 0;
906  }
907 
908  LOG_DEBUG("entities.unit", "DealDamageStart");
909 
910  uint32 health = victim->GetHealth();
911  LOG_DEBUG("entities.unit", "deal dmg:%d to health:%d ", damage, health);
912 
913  // duel ends when player has 1 or less hp
914  bool duel_hasEnded = false;
915  bool duel_wasMounted = false;
916  if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health - 1))
917  {
918  // xinef: situation not possible earlier, just return silently.
919  if (!attacker)
920  return 0;
921 
922  // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
923  if (victim->ToPlayer()->duel->opponent == attacker || victim->ToPlayer()->duel->opponent->GetGUID() == attacker->GetOwnerGUID())
924  damage = health - 1;
925 
926  duel_hasEnded = true;
927  }
928  else if (victim->IsVehicle() && damage >= (health - 1) && victim->GetCharmer() && victim->GetCharmer()->GetTypeId() == TYPEID_PLAYER)
929  {
930  Player* victimRider = victim->GetCharmer()->ToPlayer();
931 
932  if (victimRider && victimRider->duel && victimRider->duel->isMounted)
933  {
934  // xinef: situation not possible earlier, just return silently.
935  if (!attacker)
936  return 0;
937 
938  // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
939  if (victimRider->duel->opponent == attacker || victimRider->duel->opponent->GetGUID() == attacker->GetCharmerGUID())
940  damage = health - 1;
941 
942  duel_wasMounted = true;
943  duel_hasEnded = true;
944  }
945  }
946 
947  if (attacker && attacker != victim)
948  if (Player* killer = attacker->GetCharmerOrOwnerPlayerOrPlayerItself())
949  {
950  // pussywizard: don't allow GMs to deal damage in normal way (this leaves no evidence in logs!), they have commands to do so
951  //if (!allowGM && killer->GetSession()->GetSecurity() && killer->GetSession()->GetSecurity() <= SEC_ADMINISTRATOR)
952  // return 0;
953 
954  if (Battleground* bg = killer->GetBattleground())
955  {
956  bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
957  killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, victim); // pussywizard: InBattleground() optimization
958  }
959  //killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage); // pussywizard: optimization
960  }
961 
962  if (victim->GetTypeId() == TYPEID_PLAYER)
963  ;//victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED, damage); // pussywizard: optimization
964  else if (!victim->IsControlledByPlayer() || victim->IsVehicle())
965  {
966  if (!victim->ToCreature()->hasLootRecipient())
967  victim->ToCreature()->SetLootRecipient(attacker);
968 
969  if (!attacker || attacker->IsControlledByPlayer() || attacker->IsCreatedByPlayer())
970  victim->ToCreature()->LowerPlayerDamageReq(health < damage ? health : damage);
971  }
972 
973  if (health <= damage)
974  {
975  LOG_DEBUG("entities.unit", "DealDamage: victim just died");
976 
977  //if (attacker && victim->GetTypeId() == TYPEID_PLAYER && victim != attacker)
978  //victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health); // pussywizard: optimization
979 
980  Unit::Kill(attacker, victim, durabilityLoss, cleanDamage ? cleanDamage->attackType : BASE_ATTACK, spellProto);
981  }
982  else
983  {
984  LOG_DEBUG("entities.unit", "DealDamageAlive");
985 
986  //if (victim->GetTypeId() == TYPEID_PLAYER)
987  // victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage); // pussywizard: optimization
988 
989  victim->ModifyHealth(- (int32)damage);
990 
991  if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE)
992  victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0);
993 
994  if (victim->GetTypeId() != TYPEID_PLAYER)
995  {
996  // Part of Evade mechanics. DoT's and Thorns / Retribution Aura do not contribute to this
997  if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD)))
998  victim->ToCreature()->SetLastDamagedTime(sWorld->GetGameTime() + MAX_AGGRO_RESET_TIME);
999 
1000  if (attacker)
1001  victim->AddThreat(attacker, float(damage), damageSchoolMask, spellProto);
1002  }
1003  else // victim is a player
1004  {
1005  // random durability for items (HIT TAKEN)
1007  {
1009  victim->ToPlayer()->DurabilityPointLossForEquipSlot(slot);
1010  }
1011  }
1012 
1013  // Rage from damage received
1014  if (attacker != victim && victim->getPowerType() == POWER_RAGE)
1015  {
1016  uint32 rageDamage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
1017  victim->RewardRage(rageDamage, 0, false);
1018  }
1019 
1020  if (attacker && attacker->GetTypeId() == TYPEID_PLAYER)
1021  {
1022  // random durability for items (HIT DONE)
1024  {
1026  attacker->ToPlayer()->DurabilityPointLossForEquipSlot(slot);
1027  }
1028  }
1029 
1030  if (damagetype != NODAMAGE && damage && (!spellProto || !(spellProto->HasAttribute(SPELL_ATTR3_TREAT_AS_PERIODIC) || spellProto->HasAttribute(SPELL_ATTR7_DONT_CAUSE_SPELL_PUSHBACK))))
1031  {
1032  if (victim != attacker && victim->GetTypeId() == TYPEID_PLAYER) // does not support creature push_back
1033  {
1034  if (damagetype != DOT)
1035  if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
1036  if (spell->getState() == SPELL_STATE_PREPARING)
1037  {
1038  uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
1039  if (interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG)
1040  victim->InterruptNonMeleeSpells(false);
1041  else if (interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK)
1042  spell->Delayed();
1043  }
1044 
1045  if (Spell* spell = victim->m_currentSpells[CURRENT_CHANNELED_SPELL])
1046  if (spell->getState() == SPELL_STATE_CASTING)
1047  {
1048  uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags;
1049  if (((channelInterruptFlags & CHANNEL_FLAG_DELAY) != 0) && (damagetype != DOT))
1050  spell->DelayedChannel();
1051  }
1052  }
1053  }
1054 
1055  // last damage from duel opponent
1056  if (duel_hasEnded)
1057  {
1058  Player* he = duel_wasMounted ? victim->GetCharmer()->ToPlayer() : victim->ToPlayer();
1059 
1060  ASSERT(he && he->duel);
1061 
1062  if (duel_wasMounted) // In this case victim==mount
1063  victim->SetHealth(1);
1064  else
1065  he->SetHealth(1);
1066 
1067  he->duel->opponent->CombatStopWithPets(true);
1068  he->CombatStopWithPets(true);
1069 
1070  he->CastSpell(he, 7267, true); // beg
1071  he->DuelComplete(DUEL_WON);
1072  }
1073  }
1074 
1075  LOG_DEBUG("entities.unit", "DealDamageEnd returned %d damage", damage);
1076 
1077  return damage;
1078 }
1079 
1080 void Unit::CastStop(uint32 except_spellid, bool withInstant)
1081 {
1083  if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id != except_spellid)
1084  InterruptSpell(CurrentSpellTypes(i), false, withInstant);
1085 }
1086 
1087 SpellCastResult Unit::CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1088 {
1089  if (!spellInfo)
1090  {
1091  LOG_ERROR("entities.unit", "CastSpell: unknown spell by caster %s", GetGUID().ToString().c_str());
1093  }
1094 
1095  // TODO: this is a workaround - not needed anymore, but required for some scripts :(
1096  if (!originalCaster && triggeredByAura)
1097  {
1098  originalCaster = triggeredByAura->GetCasterGUID();
1099  }
1100 
1101  Spell* spell = new Spell(this, spellInfo, triggerFlags, originalCaster);
1102 
1103  if (value)
1104  {
1105  for (CustomSpellValues::const_iterator itr = value->begin(); itr != value->end(); ++itr)
1106  {
1107  spell->SetSpellValue(itr->first, itr->second);
1108  }
1109  }
1110 
1111  spell->m_CastItem = castItem;
1112  return spell->prepare(&targets, triggeredByAura);
1113 }
1114 
1115 SpellCastResult Unit::CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1116 {
1117  return CastSpell(victim, spellId, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1118 }
1119 
1120 SpellCastResult Unit::CastSpell(Unit* victim, uint32 spellId, TriggerCastFlags triggerFlags /*= TRIGGER_NONE*/, Item* castItem /*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
1121 {
1122  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
1123  if (!spellInfo)
1124  {
1125  LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str());
1127  }
1128 
1129  return CastSpell(victim, spellInfo, triggerFlags, castItem, triggeredByAura, originalCaster);
1130 }
1131 
1132 SpellCastResult Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, bool triggered, Item* castItem/*= nullptr*/, AuraEffect const* triggeredByAura /*= nullptr*/, ObjectGuid originalCaster /*= ObjectGuid::Empty*/)
1133 {
1134  return CastSpell(victim, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1135 }
1136 
1137 SpellCastResult Unit::CastSpell(Unit* victim, SpellInfo const* spellInfo, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1138 {
1139  SpellCastTargets targets;
1140  targets.SetUnitTarget(victim);
1141  return CastSpell(targets, spellInfo, nullptr, triggerFlags, castItem, triggeredByAura, originalCaster);
1142 }
1143 
1144 SpellCastResult Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1145 {
1146  CustomSpellValues values;
1147  if (bp0)
1148  values.AddSpellMod(SPELLVALUE_BASE_POINT0, *bp0);
1149  if (bp1)
1150  values.AddSpellMod(SPELLVALUE_BASE_POINT1, *bp1);
1151  if (bp2)
1152  values.AddSpellMod(SPELLVALUE_BASE_POINT2, *bp2);
1153  return CastCustomSpell(spellId, values, target, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1154 }
1155 
1156 SpellCastResult Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1157 {
1158  CustomSpellValues values;
1159  values.AddSpellMod(mod, value);
1160  return CastCustomSpell(spellId, values, target, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1161 }
1162 
1163 SpellCastResult Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1164 {
1165  CustomSpellValues values;
1166  values.AddSpellMod(mod, value);
1167  return CastCustomSpell(spellId, values, target, triggerFlags, castItem, triggeredByAura, originalCaster);
1168 }
1169 
1170 SpellCastResult Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit* victim, TriggerCastFlags triggerFlags, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1171 {
1172  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
1173  if (!spellInfo)
1174  {
1175  LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str());
1177  }
1178 
1179  SpellCastTargets targets;
1180  targets.SetUnitTarget(victim);
1181 
1182  return CastSpell(targets, spellInfo, &value, triggerFlags, castItem, triggeredByAura, originalCaster);
1183 }
1184 
1185 SpellCastResult Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem, AuraEffect const* triggeredByAura, ObjectGuid originalCaster)
1186 {
1187  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
1188  if (!spellInfo)
1189  {
1190  LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str());
1192  }
1193 
1194  SpellCastTargets targets;
1195  targets.SetDst(x, y, z, GetOrientation());
1196 
1197  return CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1198 }
1199 
1200 SpellCastResult Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, AuraEffect* triggeredByAura, ObjectGuid originalCaster)
1201 {
1202  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
1203  if (!spellInfo)
1204  {
1205  LOG_ERROR("entities.unit", "CastSpell: unknown spell %u by caster %s", spellId, GetGUID().ToString().c_str());
1207  }
1208 
1209  SpellCastTargets targets;
1210  targets.SetGOTarget(go);
1211 
1212  return CastSpell(targets, spellInfo, nullptr, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, castItem, triggeredByAura, originalCaster);
1213 }
1214 
1215 void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType, bool crit)
1216 {
1217  if (damage < 0)
1218  return;
1219 
1220  Unit* victim = damageInfo->target;
1221  if (!victim || !victim->IsAlive())
1222  return;
1223 
1224  SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
1225  uint32 crTypeMask = victim->GetCreatureTypeMask();
1226 
1227  // Script Hook For CalculateSpellDamageTaken -- Allow scripts to change the Damage post class mitigation calculations
1228  sScriptMgr->ModifySpellDamageTaken(damageInfo->target, damageInfo->attacker, damage);
1229 
1230  if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo))
1231  {
1232  damageInfo->damage = Unit::CalcArmorReducedDamage(this, victim, damage, spellInfo, 0, attackType);
1233  damageInfo->cleanDamage += damage - damageInfo->damage;
1234  }
1235  else
1236  damageInfo->damage = damage;
1237 
1238  bool blocked = false;
1239  // Per-school calc
1240  switch (spellInfo->DmgClass)
1241  {
1242  // Melee and Ranged Spells
1245  {
1246  // Physical Damage
1247  if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
1248  {
1249  // Get blocked status
1250  blocked = isSpellBlocked(victim, spellInfo, attackType);
1251  }
1252 
1253  if (crit)
1254  {
1255  damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
1256 
1257  // Calculate crit bonus
1258  uint32 crit_bonus = damageInfo->damage;
1259  // Apply crit_damage bonus for melee spells
1260  if (Player* modOwner = GetSpellModOwner())
1261  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
1262  damageInfo->damage += crit_bonus;
1263 
1264  // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1265  float critPctDamageMod = 0.0f;
1266  if (attackType == RANGED_ATTACK)
1268  else
1270 
1271  // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
1273 
1274  // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1275  critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
1276 
1277  if (critPctDamageMod != 0)
1278  AddPct(damageInfo->damage, critPctDamageMod);
1279  }
1280 
1281  // Spell weapon based damage CAN BE crit & blocked at same time
1282  if (blocked)
1283  {
1284  damageInfo->blocked = victim->GetShieldBlockValue();
1285  // double blocked amount if block is critical
1286  if (victim->isBlockCritical())
1287  damageInfo->blocked *= 2;
1288  if (damage < int32(damageInfo->blocked))
1289  damageInfo->blocked = uint32(damage);
1290 
1291  damageInfo->damage -= damageInfo->blocked;
1292  damageInfo->cleanDamage += damageInfo->blocked;
1293  }
1294 
1295  int32 resilienceReduction = damageInfo->damage;
1296  if (CanApplyResilience())
1297  {
1298  if (attackType != RANGED_ATTACK)
1299  Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_MELEE);
1300  else
1301  Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_RANGED);
1302  }
1303 
1304  resilienceReduction = damageInfo->damage - resilienceReduction;
1305  damageInfo->damage -= resilienceReduction;
1306  damageInfo->cleanDamage += resilienceReduction;
1307  break;
1308  }
1309  // Magical Attacks
1312  {
1313  // If crit add critical bonus
1314  if (crit)
1315  {
1316  damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
1317  damageInfo->damage = Unit::SpellCriticalDamageBonus(this, spellInfo, damageInfo->damage, victim);
1318  }
1319 
1320  int32 resilienceReduction = damageInfo->damage;
1321  if (CanApplyResilience())
1322  Unit::ApplyResilience(victim, nullptr, &resilienceReduction, crit, CR_CRIT_TAKEN_SPELL);
1323 
1324  resilienceReduction = damageInfo->damage - resilienceReduction;
1325  damageInfo->damage -= resilienceReduction;
1326  damageInfo->cleanDamage += resilienceReduction;
1327  break;
1328  }
1329  default:
1330  break;
1331  }
1332 
1333  // Calculate absorb resist
1334  if (int32(damageInfo->damage) > 0)
1335  {
1336  DamageInfo dmgInfo(*damageInfo, SPELL_DIRECT_DAMAGE);
1337  Unit::CalcAbsorbResist(dmgInfo);
1338  damageInfo->absorb = dmgInfo.GetAbsorb();
1339  damageInfo->resist = dmgInfo.GetResist();
1340  damageInfo->damage = dmgInfo.GetDamage();
1341  }
1342  else
1343  damageInfo->damage = 0;
1344 }
1345 
1346 void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
1347 {
1348  if (damageInfo == 0)
1349  return;
1350 
1351  Unit* victim = damageInfo->target;
1352 
1353  if (!victim)
1354  return;
1355 
1356  if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
1357  return;
1358 
1359  SpellInfo const* spellProto = damageInfo->spellInfo;
1360  if (!spellProto)
1361  {
1362  LOG_DEBUG("entities.unit", "Unit::DealSpellDamage has wrong damageInfo");
1363  return;
1364  }
1365 
1366  // Call default DealDamage
1367  CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL);
1368  Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
1369 }
1370 
1371 // TODO for melee need create structure as in
1372 void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType, const bool sittingVictim)
1373 {
1374  damageInfo->attacker = this;
1375  damageInfo->target = victim;
1377  damageInfo->attackType = attackType;
1378  damageInfo->damage = 0;
1379  damageInfo->cleanDamage = 0;
1380  damageInfo->absorb = 0;
1381  damageInfo->resist = 0;
1382  damageInfo->blocked_amount = 0;
1383 
1384  damageInfo->TargetState = 0;
1385  damageInfo->HitInfo = 0;
1386  damageInfo->procAttacker = PROC_FLAG_NONE;
1387  damageInfo->procVictim = PROC_FLAG_NONE;
1388  damageInfo->procEx = PROC_EX_NONE;
1389  damageInfo->hitOutCome = MELEE_HIT_EVADE;
1390 
1391  if (!victim)
1392  return;
1393 
1394  if (!IsAlive() || !victim->IsAlive())
1395  return;
1396 
1397  // Select HitInfo/procAttacker/procVictim flag based on attack type
1398  switch (attackType)
1399  {
1400  case BASE_ATTACK:
1403  break;
1404  case OFF_ATTACK:
1407  damageInfo->HitInfo = HITINFO_OFFHAND;
1408  break;
1409  default:
1410  return;
1411  }
1412 
1413  // Physical Immune check
1414  if (damageInfo->target->IsImmunedToDamageOrSchool(SpellSchoolMask(damageInfo->damageSchoolMask)))
1415  {
1416  damageInfo->HitInfo |= HITINFO_NORMALSWING;
1417  damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
1418 
1419  damageInfo->procEx |= PROC_EX_IMMUNE;
1420  return;
1421  }
1422 
1423  damage += CalculateDamage(damageInfo->attackType, false, true);
1424  // Add melee damage bonus
1425  damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
1426  damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
1427 
1428  // Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations
1429  sScriptMgr->ModifyMeleeDamage(damageInfo->target, damageInfo->attacker, damage);
1430 
1431  // Calculate armor reduction
1433  {
1434  damageInfo->damage = Unit::CalcArmorReducedDamage(this, damageInfo->target, damage, nullptr, 0, damageInfo->attackType);
1435  damageInfo->cleanDamage += damage - damageInfo->damage;
1436  }
1437  else
1438  damageInfo->damage = damage;
1439 
1440  damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
1441 
1442  // If the victim was a sitting player and we didn't roll a miss, then crit.
1443  if (sittingVictim && damageInfo->hitOutCome != MELEE_HIT_MISS)
1444  {
1445  damageInfo->hitOutCome = MELEE_HIT_CRIT;
1446  }
1447  switch (damageInfo->hitOutCome)
1448  {
1449  case MELEE_HIT_EVADE:
1450  damageInfo->HitInfo |= HITINFO_MISS | HITINFO_SWINGNOHITSOUND;
1451  damageInfo->TargetState = VICTIMSTATE_EVADES;
1452  damageInfo->procEx |= PROC_EX_EVADE;
1453  damageInfo->damage = 0;
1454  damageInfo->cleanDamage = 0;
1455  return;
1456  case MELEE_HIT_MISS:
1457  damageInfo->HitInfo |= HITINFO_MISS;
1458  damageInfo->TargetState = VICTIMSTATE_INTACT;
1459  damageInfo->procEx |= PROC_EX_MISS;
1460  damageInfo->damage = 0;
1461  damageInfo->cleanDamage = 0;
1462  break;
1463  case MELEE_HIT_NORMAL:
1464  damageInfo->TargetState = VICTIMSTATE_HIT;
1465  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1466  break;
1467  case MELEE_HIT_CRIT:
1468  {
1469  damageInfo->HitInfo |= HITINFO_CRITICALHIT;
1470  damageInfo->TargetState = VICTIMSTATE_HIT;
1471 
1472  damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
1473  // Crit bonus calc
1474  damageInfo->damage += damageInfo->damage;
1475  float mod = 0.0f;
1476  // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1477  if (damageInfo->attackType == RANGED_ATTACK)
1479  else
1480  {
1482 
1483  // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
1485  }
1486 
1487  uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
1488 
1489  // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1491  if (mod != 0)
1492  AddPct(damageInfo->damage, mod);
1493  break;
1494  }
1495  case MELEE_HIT_PARRY:
1496  damageInfo->TargetState = VICTIMSTATE_PARRY;
1497  damageInfo->procEx |= PROC_EX_PARRY;
1498  damageInfo->cleanDamage += damageInfo->damage;
1499  damageInfo->damage = 0;
1500  break;
1501  case MELEE_HIT_DODGE:
1502  damageInfo->TargetState = VICTIMSTATE_DODGE;
1503  damageInfo->procEx |= PROC_EX_DODGE;
1504  damageInfo->cleanDamage += damageInfo->damage;
1505  damageInfo->damage = 0;
1506  break;
1507  case MELEE_HIT_BLOCK:
1508  damageInfo->TargetState = VICTIMSTATE_HIT;
1509  damageInfo->HitInfo |= HITINFO_BLOCK;
1510  damageInfo->procEx |= PROC_EX_BLOCK;
1511  damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
1512  // double blocked amount if block is critical
1513  if (damageInfo->target->isBlockCritical())
1514  damageInfo->blocked_amount += damageInfo->blocked_amount;
1515  if (damageInfo->blocked_amount >= damageInfo->damage)
1516  {
1517  damageInfo->TargetState = VICTIMSTATE_BLOCKS;
1518  damageInfo->blocked_amount = damageInfo->damage;
1519  damageInfo->procEx |= PROC_EX_FULL_BLOCK;
1520  }
1521  else
1522  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1523  damageInfo->damage -= damageInfo->blocked_amount;
1524  damageInfo->cleanDamage += damageInfo->blocked_amount;
1525  break;
1526  case MELEE_HIT_GLANCING:
1527  {
1528  damageInfo->HitInfo |= HITINFO_GLANCING;
1529  damageInfo->TargetState = VICTIMSTATE_HIT;
1530  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1531  int32 leveldif = int32(victim->getLevel()) - int32(getLevel());
1532  if (leveldif > 3)
1533  leveldif = 3;
1534  float reducePercent = 1 - leveldif * 0.1f;
1535  damageInfo->cleanDamage += damageInfo->damage - uint32(reducePercent * damageInfo->damage);
1536  damageInfo->damage = uint32(reducePercent * damageInfo->damage);
1537  break;
1538  }
1539  case MELEE_HIT_CRUSHING:
1540  damageInfo->HitInfo |= HITINFO_CRUSHING;
1541  damageInfo->TargetState = VICTIMSTATE_HIT;
1542  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1543  // 150% normal damage
1544  damageInfo->damage += (damageInfo->damage / 2);
1545  break;
1546  default:
1547  break;
1548  }
1549 
1550  // Always apply HITINFO_AFFECTS_VICTIM in case its not a miss
1551  if (!(damageInfo->HitInfo & HITINFO_MISS))
1552  damageInfo->HitInfo |= HITINFO_AFFECTS_VICTIM;
1553 
1554  int32 resilienceReduction = damageInfo->damage;
1555 
1556  // attackType is checked already for BASE_ATTACK or OFF_ATTACK so it can't be RANGED_ATTACK here
1558  Unit::ApplyResilience(victim, nullptr, &resilienceReduction, (damageInfo->hitOutCome == MELEE_HIT_CRIT), CR_CRIT_TAKEN_MELEE);
1559 
1560  resilienceReduction = damageInfo->damage - resilienceReduction;
1561  damageInfo->damage -= resilienceReduction;
1562  damageInfo->cleanDamage += resilienceReduction;
1563 
1564  // Calculate absorb resist
1565  if (int32(damageInfo->damage) > 0)
1566  {
1567  damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
1568  // Calculate absorb & resists
1569 
1570  DamageInfo dmgInfo(*damageInfo);
1571  Unit::CalcAbsorbResist(dmgInfo);
1572  damageInfo->absorb = dmgInfo.GetAbsorb();
1573  damageInfo->resist = dmgInfo.GetResist();
1574 
1575  if (damageInfo->absorb)
1576  {
1577  damageInfo->HitInfo |= (damageInfo->damage - damageInfo->absorb == 0 ? HITINFO_FULL_ABSORB : HITINFO_PARTIAL_ABSORB);
1578  damageInfo->procEx |= PROC_EX_ABSORB;
1579  }
1580 
1581  if (damageInfo->resist)
1582  damageInfo->HitInfo |= (damageInfo->damage - damageInfo->resist == 0 ? HITINFO_FULL_RESIST : HITINFO_PARTIAL_RESIST);
1583 
1584  damageInfo->damage = dmgInfo.GetDamage();
1585  }
1586  else // Impossible get negative result but....
1587  damageInfo->damage = 0;
1588 }
1589 
1590 void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
1591 {
1592  Unit* victim = damageInfo->target;
1593 
1594  if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
1595  return;
1596 
1597  // Hmmmm dont like this emotes client must by self do all animations
1598  if (damageInfo->HitInfo & HITINFO_CRITICALHIT)
1600  if (damageInfo->blocked_amount && damageInfo->TargetState != VICTIMSTATE_BLOCKS)
1602 
1603  if (damageInfo->TargetState == VICTIMSTATE_PARRY)
1604  {
1605  // Get attack timers
1606  float offtime = float(victim->getAttackTimer(OFF_ATTACK));
1607  float basetime = float(victim->getAttackTimer(BASE_ATTACK));
1608  // Reduce attack time
1609  if (victim->haveOffhandWeapon() && offtime < basetime)
1610  {
1611  float percent20 = victim->GetAttackTime(OFF_ATTACK) * 0.20f;
1612  float percent60 = 3.0f * percent20;
1613  if (offtime > percent20 && offtime <= percent60)
1614  victim->setAttackTimer(OFF_ATTACK, uint32(percent20));
1615  else if (offtime > percent60)
1616  {
1617  offtime -= 2.0f * percent20;
1618  victim->setAttackTimer(OFF_ATTACK, uint32(offtime));
1619  }
1620  }
1621  else
1622  {
1623  float percent20 = victim->GetAttackTime(BASE_ATTACK) * 0.20f;
1624  float percent60 = 3.0f * percent20;
1625  if (basetime > percent20 && basetime <= percent60)
1626  victim->setAttackTimer(BASE_ATTACK, uint32(percent20));
1627  else if (basetime > percent60)
1628  {
1629  basetime -= 2.0f * percent20;
1630  victim->setAttackTimer(BASE_ATTACK, uint32(basetime));
1631  }
1632  }
1633  }
1634 
1635  // Call default DealDamage
1636  CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, damageInfo->attackType, damageInfo->hitOutCome);
1637  Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), nullptr, durabilityLoss);
1638 
1639  // If this is a creature and it attacks from behind it has a probability to daze it's victim
1640  if (damageInfo->damage && ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
1641  GetTypeId() != TYPEID_PLAYER && !ToCreature()->IsControlledByPlayer() && !victim->HasInArc(M_PI, this)
1642  && (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss()) && !victim->IsVehicle()))
1643  {
1644  // -probability is between 0% and 40%
1645  // 20% base chance
1646  float Probability = 20.0f;
1647 
1648  // there is a newbie protection, at level 10 just 7% base chance; assuming linear function
1649  if (victim->getLevel() < 30)
1650  Probability = 0.65f * victim->getLevel() + 0.5f;
1651 
1652  uint32 VictimDefense = victim->GetDefenseSkillValue();
1653  uint32 AttackerMeleeSkill = GetUnitMeleeSkill();
1654 
1655  // xinef: fix daze mechanics
1656  Probability -= ((float)VictimDefense - AttackerMeleeSkill) * 0.1428f;
1657 
1658  if (Probability > 40.0f)
1659  Probability = 40.0f;
1660 
1661  if (roll_chance_f(std::max(0.0f, Probability)))
1662  CastSpell(victim, 1604, true);
1663  }
1664 
1665  if (GetTypeId() == TYPEID_PLAYER)
1666  ToPlayer()->CastItemCombatSpell(victim, damageInfo->attackType, damageInfo->procVictim, damageInfo->procEx);
1667 
1668  // Do effect if any damage done to target
1669  if (damageInfo->damage)
1670  {
1671  // We're going to call functions which can modify content of the list during iteration over it's elements
1672  // Let's copy the list so we can prevent iterator invalidation
1673  AuraEffectList vDamageShieldsCopy(victim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD));
1674  for (AuraEffectList::const_iterator dmgShieldItr = vDamageShieldsCopy.begin(); dmgShieldItr != vDamageShieldsCopy.end(); ++dmgShieldItr)
1675  {
1676  SpellInfo const* i_spellProto = (*dmgShieldItr)->GetSpellInfo();
1677  // Damage shield can be resisted...
1678  if (SpellMissInfo missInfo = victim->SpellHitResult(this, i_spellProto, false))
1679  {
1680  victim->SendSpellMiss(this, i_spellProto->Id, missInfo);
1681  continue;
1682  }
1683 
1684  // ...or immuned
1685  if (IsImmunedToDamageOrSchool(i_spellProto))
1686  {
1687  victim->SendSpellDamageImmune(this, i_spellProto->Id);
1688  continue;
1689  }
1690 
1691  uint32 damage = uint32(std::max(0, (*dmgShieldItr)->GetAmount())); // xinef: done calculated at amount calculation
1692 
1693  if (Unit* caster = (*dmgShieldItr)->GetCaster())
1694  damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
1695 
1696  uint32 absorb = 0;
1697 
1698  DamageInfo dmgInfo(victim, this, damage, i_spellProto, i_spellProto->GetSchoolMask(), SPELL_DIRECT_DAMAGE);
1699  Unit::CalcAbsorbResist(dmgInfo);
1700  absorb = dmgInfo.GetAbsorb();
1701  damage = dmgInfo.GetDamage();
1702 
1703  Unit::DealDamageMods(this, damage, &absorb);
1704 
1705  // TODO: Move this to a packet handler
1706  WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8 + 8 + 4 + 4 + 4 + 4));
1707  data << victim->GetGUID();
1708  data << GetGUID();
1709  data << uint32(i_spellProto->Id);
1710  data << uint32(damage); // Damage
1711  int32 overkill = int32(damage) - int32(GetHealth());
1712  data << uint32(overkill > 0 ? overkill : 0); // Overkill
1713  data << uint32(i_spellProto->GetSchoolMask());
1714  victim->SendMessageToSet(&data, true);
1715 
1716  Unit::DealDamage(victim, this, damage, 0, SPELL_DIRECT_DAMAGE, i_spellProto->GetSchoolMask(), i_spellProto, true);
1717  }
1718  }
1719 }
1720 
1722 {
1723  WorldPacket data(SMSG_EMOTE, 4 + 8);
1724  data << uint32(anim_id);
1725  data << GetGUID();
1726  SendMessageToSet(&data, true);
1727 }
1728 
1729 bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* spellInfo, uint8 effIndex)
1730 {
1731  // only physical spells damage gets reduced by armor
1732  if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
1733  return false;
1734  if (spellInfo)
1735  {
1736  // there are spells with no specific attribute but they have "ignores armor" in tooltip
1737  if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_ARMOR))
1738  return false;
1739 
1740  // bleeding effects are not reduced by armor
1741  if (effIndex != MAX_SPELL_EFFECTS)
1742  {
1743  if (spellInfo->Effects[effIndex].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE ||
1744  spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
1745  if (spellInfo->GetEffectMechanicMask(effIndex) & (1 << MECHANIC_BLEED))
1746  return false;
1747  }
1748  }
1749  return true;
1750 }
1751 
1752 uint32 Unit::CalcArmorReducedDamage(Unit const* attacker, Unit const* victim, const uint32 damage, SpellInfo const* spellInfo, uint8 attackerLevel, WeaponAttackType /*attackType*/)
1753 {
1754  uint32 newdamage = 0;
1755  float armor = float(victim->GetArmor());
1756 
1757  // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
1758  if (attacker)
1759  {
1761 
1762  if (spellInfo)
1763  if (Player* modOwner = attacker->GetSpellModOwner())
1764  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor);
1765 
1767  for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
1768  {
1769  if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL
1770  && (*j)->IsAffectedOnSpell(spellInfo))
1771  armor = floor(AddPct(armor, -(*j)->GetAmount()));
1772  }
1773 
1774  AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
1775  for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
1776  {
1777  if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
1778  armor = floor(AddPct(armor, -(*j)->GetAmount()));
1779  }
1780 
1781  // Apply Player CR_ARMOR_PENETRATION rating and buffs from stances\specializations etc.
1782  if (attacker->GetTypeId() == TYPEID_PLAYER)
1783  {
1784  float bonusPct = 0;
1786  for (AuraEffectList::const_iterator itr = armorPenAuras.begin(); itr != armorPenAuras.end(); ++itr)
1787  {
1788  if ((*itr)->GetSpellInfo()->EquippedItemClass == -1)
1789  {
1790  if (!spellInfo || (*itr)->IsAffectedOnSpell(spellInfo) || (*itr)->GetMiscValue() & spellInfo->GetSchoolMask())
1791  bonusPct += (*itr)->GetAmount();
1792  else if (!(*itr)->GetMiscValue() && !(*itr)->HasSpellClassMask())
1793  bonusPct += (*itr)->GetAmount();
1794  }
1795  else
1796  {
1797  if (attacker->ToPlayer()->HasItemFitToSpellRequirements((*itr)->GetSpellInfo()))
1798  bonusPct += (*itr)->GetAmount();
1799  }
1800  }
1801 
1802  float maxArmorPen = 0;
1803  if (victim->getLevel() < 60)
1804  maxArmorPen = float(400 + 85 * victim->getLevel());
1805  else
1806  maxArmorPen = 400 + 85 * victim->getLevel() + 4.5f * 85 * (victim->getLevel() - 59);
1807 
1808  // Cap armor penetration to this number
1809  maxArmorPen = std::min((armor + maxArmorPen) / 3, armor);
1810  // Figure out how much armor do we ignore
1811  float armorPen = CalculatePct(maxArmorPen, bonusPct + attacker->ToPlayer()->GetRatingBonusValue(CR_ARMOR_PENETRATION));
1812  // Got the value, apply it
1813  armor -= std::min(armorPen, maxArmorPen);
1814  }
1815  }
1816 
1817  if (armor < 0.0f)
1818  armor = 0.0f;
1819 
1820  float levelModifier = attacker ? attacker->getLevel() : attackerLevel;
1821  if (levelModifier > 59)
1822  levelModifier = levelModifier + (4.5f * (levelModifier - 59));
1823 
1824  float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40);
1825  tmpvalue = tmpvalue / (1.0f + tmpvalue);
1826 
1827  if (tmpvalue < 0.0f)
1828  tmpvalue = 0.0f;
1829  if (tmpvalue > 0.75f)
1830  tmpvalue = 0.75f;
1831 
1832  newdamage = uint32(damage - (damage * tmpvalue));
1833 
1834  return (newdamage > 1) ? newdamage : 1;
1835 }
1836 
1837 float Unit::GetEffectiveResistChance(Unit const* owner, SpellSchoolMask schoolMask, Unit const* victim, SpellInfo const* spellInfo)
1838 {
1839  float victimResistance = float(victim->GetResistance(schoolMask));
1840  if (owner)
1841  {
1842  // Xinef: pets inherit 100% of masters penetration
1843  // Xinef: excluding traps
1844  Player const* player = owner->GetSpellModOwner();
1845  if (player && owner->GetEntry() != WORLD_TRIGGER)
1846  {
1847  victimResistance += float(player->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
1848  victimResistance -= float(player->GetSpellPenetrationItemMod());
1849  }
1850  else
1851  victimResistance += float(owner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask));
1852  }
1853 
1854  // Chaos Bolt exception, ignore all target resistances (unknown attribute?)
1855  if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && spellInfo->SpellIconID == 3178)
1856  victimResistance = 0;
1857 
1858  victimResistance = std::max(victimResistance, 0.0f);
1859  if (owner)
1860  victimResistance += std::max((float(victim->getLevel()) - float(owner->getLevel())) * 5.0f, 0.0f);
1861 
1862  static uint32 const BOSS_LEVEL = 83;
1863  static float const BOSS_RESISTANCE_CONSTANT = 510.0f;
1864  uint32 level = victim->getLevel();
1865  float resistanceConstant = 0.0f;
1866 
1867  if (level == BOSS_LEVEL)
1868  resistanceConstant = BOSS_RESISTANCE_CONSTANT;
1869  else
1870  resistanceConstant = level * 5.0f;
1871 
1872  return victimResistance / (victimResistance + resistanceConstant);
1873 }
1874 
1875 void Unit::CalcAbsorbResist(DamageInfo& dmgInfo, bool Splited)
1876 {
1877  Unit* victim = dmgInfo.GetVictim();
1878  Unit* attacker = dmgInfo.GetAttacker();
1879  uint32 damage = dmgInfo.GetDamage();
1880  SpellSchoolMask schoolMask = dmgInfo.GetSchoolMask();
1881  SpellInfo const* spellInfo = dmgInfo.GetSpellInfo();
1882 
1883  if (!victim || !victim->IsAlive() || !damage)
1884  return;
1885 
1886  // Magic damage, check for resists
1887  // Ignore spells that cant be resisted
1888  // Xinef: holy resistance exists for npcs
1889  if (!(schoolMask & SPELL_SCHOOL_MASK_NORMAL) && (!(schoolMask & SPELL_SCHOOL_MASK_HOLY) || victim->GetTypeId() == TYPEID_UNIT) && (!spellInfo || (!spellInfo->HasAttribute(SPELL_ATTR0_CU_BINARY_SPELL) && !spellInfo->HasAttribute(SPELL_ATTR4_NO_CAST_LOG))))
1890  {
1891  float averageResist = Unit::GetEffectiveResistChance(attacker, schoolMask, victim, spellInfo);
1892 
1893  float discreteResistProbability[11];
1894  for (uint32 i = 0; i < 11; ++i)
1895  {
1896  discreteResistProbability[i] = 0.5f - 2.5f * fabs(0.1f * i - averageResist);
1897  if (discreteResistProbability[i] < 0.0f)
1898  discreteResistProbability[i] = 0.0f;
1899  }
1900 
1901  if (averageResist <= 0.1f)
1902  {
1903  discreteResistProbability[0] = 1.0f - 7.5f * averageResist;
1904  discreteResistProbability[1] = 5.0f * averageResist;
1905  discreteResistProbability[2] = 2.5f * averageResist;
1906  }
1907 
1908  float r = float(rand_norm());
1909  uint32 i = 0;
1910  float probabilitySum = discreteResistProbability[0];
1911 
1912  while (r >= probabilitySum && i < 10)
1913  probabilitySum += discreteResistProbability[++i];
1914 
1915  float damageResisted = float(damage * i / 10);
1916 
1917  if (damageResisted) // if equal to 0, checking these is pointless
1918  {
1919  if (attacker)
1920  {
1922  for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j)
1923  if (((*j)->GetMiscValue() & schoolMask) && (*j)->IsAffectedOnSpell(spellInfo))
1924  AddPct(damageResisted, -(*j)->GetAmount());
1925 
1926  AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
1927  for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
1928  if ((*j)->GetMiscValue() & schoolMask)
1929  AddPct(damageResisted, -(*j)->GetAmount());
1930  }
1931 
1932  // pussywizard:
1933  if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC))
1934  {
1935  uint32 damageAfterArmor = Unit::CalcArmorReducedDamage(attacker, victim, damage, spellInfo, 0, BASE_ATTACK);
1936  uint32 armorReduction = damage - damageAfterArmor;
1937  if (armorReduction < damageResisted) // pick the lower one, the weakest resistance counts
1938  damageResisted = armorReduction;
1939  }
1940  }
1941 
1942  dmgInfo.ResistDamage(uint32(damageResisted));
1943  }
1944 
1945  // Ignore Absorption Auras
1946  float auraAbsorbMod = 0;
1947  if (attacker)
1948  {
1949  AuraEffectList const& AbsIgnoreAurasA = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL);
1950  for (AuraEffectList::const_iterator itr = AbsIgnoreAurasA.begin(); itr != AbsIgnoreAurasA.end(); ++itr)
1951  {
1952  if (!((*itr)->GetMiscValue() & schoolMask))
1953  continue;
1954 
1955  if ((*itr)->GetAmount() > auraAbsorbMod)
1956  auraAbsorbMod = float((*itr)->GetAmount());
1957  }
1958 
1960  for (AuraEffectList::const_iterator itr = AbsIgnoreAurasB.begin(); itr != AbsIgnoreAurasB.end(); ++itr)
1961  {
1962  if (!((*itr)->GetMiscValue() & schoolMask))
1963  continue;
1964 
1965  if (((*itr)->GetAmount() > auraAbsorbMod) && (*itr)->IsAffectedOnSpell(spellInfo))
1966  auraAbsorbMod = float((*itr)->GetAmount());
1967  }
1968  RoundToInterval(auraAbsorbMod, 0.0f, 100.0f);
1969  }
1970 
1971  // We're going to call functions which can modify content of the list during iteration over it's elements
1972  // Let's copy the list so we can prevent iterator invalidation
1973  AuraEffectList vSchoolAbsorbCopy(victim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB));
1974  vSchoolAbsorbCopy.sort(Acore::AbsorbAuraOrderPred());
1975 
1976  // absorb without mana cost
1977  for (AuraEffectList::iterator itr = vSchoolAbsorbCopy.begin(); (itr != vSchoolAbsorbCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
1978  {
1979  AuraEffect* absorbAurEff = *itr;
1980  // Check if aura was removed during iteration - we don't need to work on such auras
1981  AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
1982  if (!aurApp)
1983  continue;
1984  if (!(absorbAurEff->GetMiscValue() & schoolMask))
1985  continue;
1986 
1987  // get amount which can be still absorbed by the aura
1988  int32 currentAbsorb = absorbAurEff->GetAmount();
1989  // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety
1990  if (currentAbsorb < 0)
1991  currentAbsorb = 0;
1992 
1993  uint32 tempAbsorb = uint32(currentAbsorb);
1994 
1995  bool defaultPrevented = false;
1996 
1997  absorbAurEff->GetBase()->CallScriptEffectAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
1998  currentAbsorb = tempAbsorb;
1999 
2000  if (defaultPrevented)
2001  continue;
2002 
2003  // absorb must be smaller than the damage itself
2004  currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
2005 
2006  // xinef: do this after absorb is rounded to damage...
2007  AddPct(currentAbsorb, -auraAbsorbMod);
2008 
2009  dmgInfo.AbsorbDamage(currentAbsorb);
2010 
2011  tempAbsorb = currentAbsorb;
2012  absorbAurEff->GetBase()->CallScriptEffectAfterAbsorbHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
2013 
2014  // Check if our aura is using amount to count damage
2015  if (absorbAurEff->GetAmount() >= 0)
2016  {
2017  // Reduce shield amount
2018  absorbAurEff->SetAmount(absorbAurEff->GetAmount() - currentAbsorb);
2019  // Aura cannot absorb anything more - remove it
2020  if (absorbAurEff->GetAmount() <= 0)
2021  absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
2022  }
2023  }
2024 
2025  // absorb by mana cost
2027  for (AuraEffectList::const_iterator itr = vManaShieldCopy.begin(); (itr != vManaShieldCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
2028  {
2029  AuraEffect* absorbAurEff = *itr;
2030  // Check if aura was removed during iteration - we don't need to work on such auras
2031  AuraApplication const* aurApp = absorbAurEff->GetBase()->GetApplicationOfTarget(victim->GetGUID());
2032  if (!aurApp)
2033  continue;
2034  // check damage school mask
2035  if (!(absorbAurEff->GetMiscValue() & schoolMask))
2036  continue;
2037 
2038  // get amount which can be still absorbed by the aura
2039  int32 currentAbsorb = absorbAurEff->GetAmount();
2040  // aura with infinite absorb amount - let the scripts handle absorbtion amount, set here to 0 for safety
2041  if (currentAbsorb < 0)
2042  currentAbsorb = 0;
2043 
2044  uint32 tempAbsorb = currentAbsorb;
2045 
2046  bool defaultPrevented = false;
2047 
2048  absorbAurEff->GetBase()->CallScriptEffectManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb, defaultPrevented);
2049  currentAbsorb = tempAbsorb;
2050 
2051  if (defaultPrevented)
2052  continue;
2053 
2054  // absorb must be smaller than the damage itself
2055  currentAbsorb = RoundToInterval(currentAbsorb, 0, int32(dmgInfo.GetDamage()));
2056 
2057  // xinef: do this after absorb is rounded to damage...
2058  AddPct(currentAbsorb, -auraAbsorbMod);
2059 
2060  int32 manaReduction = currentAbsorb;
2061 
2062  // lower absorb amount by talents
2063  if (float manaMultiplier = absorbAurEff->GetSpellInfo()->Effects[absorbAurEff->GetEffIndex()].CalcValueMultiplier(absorbAurEff->GetCaster()))
2064  manaReduction = int32(float(manaReduction) * manaMultiplier);
2065 
2066  int32 manaTaken = -victim->ModifyPower(POWER_MANA, -manaReduction);
2067 
2068  // take case when mana has ended up into account
2069  currentAbsorb = currentAbsorb ? int32(float(currentAbsorb) * (float(manaTaken) / float(manaReduction))) : 0;
2070 
2071  dmgInfo.AbsorbDamage(currentAbsorb);
2072 
2073  tempAbsorb = currentAbsorb;
2074  absorbAurEff->GetBase()->CallScriptEffectAfterManaShieldHandlers(absorbAurEff, aurApp, dmgInfo, tempAbsorb);
2075 
2076  // Check if our aura is using amount to count damage
2077  if (absorbAurEff->GetAmount() >= 0)
2078  {
2079  absorbAurEff->SetAmount(absorbAurEff->GetAmount() - currentAbsorb);
2080  if ((absorbAurEff->GetAmount() <= 0))
2081  absorbAurEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL);
2082  }
2083  }
2084 
2085  // split damage auras - only when not damaging self
2086  // Xinef: not true - Warlock Hellfire
2087  if (/*victim != attacker &&*/ !Splited)
2088  {
2089  // We're going to call functions which can modify content of the list during iteration over it's elements
2090  // Let's copy the list so we can prevent iterator invalidation
2091  AuraEffectList vSplitDamageFlatCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT));
2092  for (AuraEffectList::iterator itr = vSplitDamageFlatCopy.begin(); (itr != vSplitDamageFlatCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
2093  {
2094  // Check if aura was removed during iteration - we don't need to work on such auras
2095  if (!((*itr)->GetBase()->IsAppliedOnTarget(victim->GetGUID())))
2096  continue;
2097  // check damage school mask
2098  if (!((*itr)->GetMiscValue() & schoolMask))
2099  continue;
2100 
2101  // Damage can be splitted only if aura has an alive caster
2102  Unit* caster = (*itr)->GetCaster();
2103  if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
2104  continue;
2105 
2106  int32 splitDamage = (*itr)->GetAmount();
2107 
2108  // absorb must be smaller than the damage itself
2109  splitDamage = RoundToInterval(splitDamage, 0, int32(dmgInfo.GetDamage()));
2110 
2111  dmgInfo.AbsorbDamage(splitDamage);
2112 
2113  uint32 splitted = splitDamage;
2114  uint32 splitted_absorb = 0;
2115  uint32 splitted_resist = 0;
2116 
2117  uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
2118  DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, schoolMask, dmgInfo.GetDamageType());
2119  if (caster->IsImmunedToDamageOrSchool(schoolMask))
2120  {
2121  procEx |= PROC_EX_IMMUNE;
2122  splittedDmgInfo.AbsorbDamage(splitted);
2123  }
2124  else
2125  {
2126  Unit::CalcAbsorbResist(splittedDmgInfo, true);
2127  Unit::DealDamageMods(caster, splitted, &splitted_absorb);
2128  }
2129 
2130  splitted_absorb = splittedDmgInfo.GetAbsorb();
2131  splitted_resist = splittedDmgInfo.GetResist();
2132  splitted = splittedDmgInfo.GetDamage();
2133 
2134  // create procs
2135  createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim);
2136  caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted, nullptr, -1, nullptr, &splittedDmgInfo);
2137 
2138  if (attacker)
2139  attacker->SendSpellNonMeleeDamageLog(caster, (*itr)->GetSpellInfo(), splitted, schoolMask, splitted_absorb, splitted_resist, false, 0, false);
2140 
2141  CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
2142  Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*itr)->GetSpellInfo(), false);
2143  }
2144 
2145  // We're going to call functions which can modify content of the list during iteration over it's elements
2146  // Let's copy the list so we can prevent iterator invalidation
2147  AuraEffectList vSplitDamagePctCopy(victim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT));
2148  for (AuraEffectList::iterator itr = vSplitDamagePctCopy.begin(), next; (itr != vSplitDamagePctCopy.end()) && (dmgInfo.GetDamage() > 0); ++itr)
2149  {
2150  // Check if aura was removed during iteration - we don't need to work on such auras
2151  AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(victim->GetGUID());
2152  if (!aurApp)
2153  continue;
2154 
2155  // check damage school mask
2156  if (!((*itr)->GetMiscValue() & schoolMask))
2157  continue;
2158 
2159  // Damage can be splitted only if aura has an alive caster
2160  Unit* caster = (*itr)->GetCaster();
2161  if (!caster || (caster == victim) || !caster->IsInWorld() || !caster->IsAlive())
2162  continue;
2163 
2164  // Xinef: Single Target splits require LoS
2165  const SpellInfo* splitSpellInfo = (*itr)->GetSpellInfo();
2166  if (!splitSpellInfo->Effects[(*itr)->GetEffIndex()].IsAreaAuraEffect() && !splitSpellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT))
2167  if (!caster->IsWithinLOSInMap(victim) || !caster->IsWithinDist(victim, splitSpellInfo->GetMaxRange(splitSpellInfo->IsPositive(), caster)))
2168  continue;
2169 
2170  uint32 splitDamage = CalculatePct(dmgInfo.GetDamage(), (*itr)->GetAmount());
2171  SpellSchoolMask splitSchoolMask = schoolMask;
2172 
2173  (*itr)->GetBase()->CallScriptEffectSplitHandlers(*itr, aurApp, dmgInfo, splitDamage);
2174 
2175  // absorb must be smaller than the damage itself
2176  splitDamage = RoundToInterval(splitDamage, uint32(0), uint32(dmgInfo.GetDamage()));
2177 
2178  // Roar of Sacrifice, dont absorb it
2179  if (splitSpellInfo->Id != 53480)
2180  dmgInfo.AbsorbDamage(splitDamage);
2181  else
2182  splitSchoolMask = SPELL_SCHOOL_MASK_NATURE;
2183 
2184  uint32 splitted = splitDamage;
2185  uint32 splitted_absorb = 0;
2186  uint32 splitted_resist = 0;
2187 
2188  uint32 procAttacker = 0, procVictim = 0, procEx = PROC_EX_NORMAL_HIT;
2189  DamageInfo splittedDmgInfo(attacker, caster, splitted, spellInfo, splitSchoolMask, dmgInfo.GetDamageType());
2190  if (caster->IsImmunedToDamageOrSchool(schoolMask))
2191  {
2192  procEx |= PROC_EX_IMMUNE;
2193  splittedDmgInfo.AbsorbDamage(splitted);
2194  }
2195  else
2196  {
2197  Unit::CalcAbsorbResist(splittedDmgInfo, true);
2198  Unit::DealDamageMods(caster, splitted, &splitted_absorb);
2199  }
2200 
2201  splitted_absorb = splittedDmgInfo.GetAbsorb();
2202  splitted_resist = splittedDmgInfo.GetResist();
2203  splitted = splittedDmgInfo.GetDamage();
2204 
2205  // create procs
2206  createProcFlags(spellInfo, BASE_ATTACK, false, procAttacker, procVictim);
2207  caster->ProcDamageAndSpellFor(true, attacker, procVictim, procEx, BASE_ATTACK, spellInfo, splitted);
2208 
2209  if (attacker)
2210  attacker->SendSpellNonMeleeDamageLog(caster, splitSpellInfo, splitted, splitSchoolMask, splitted_absorb, splitted_resist, false, 0, false);
2211 
2212  CleanDamage cleanDamage = CleanDamage(splitted, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
2213  Unit::DealDamage(attacker, caster, splitted, &cleanDamage, DIRECT_DAMAGE, splitSchoolMask, splitSpellInfo, false);
2214  }
2215  }
2216 }
2217 
2219 {
2220  if (!healInfo.GetHeal())
2221  return;
2222 
2223  int32 const healing = static_cast<int32>(healInfo.GetHeal());
2224  int32 absorbAmount = 0;
2225 
2226  // Need remove expired auras after
2227  bool existExpired = false;
2228 
2229  // absorb without mana cost
2231  for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end() && absorbAmount <= healing; ++i)
2232  {
2233  if (!((*i)->GetMiscValue() & healInfo.GetSpellInfo()->SchoolMask))
2234  continue;
2235 
2236  // Max Amount can be absorbed by this aura
2237  int32 currentAbsorb = (*i)->GetAmount();
2238 
2239  // Found empty aura (impossible but..)
2240  if (currentAbsorb <= 0)
2241  {
2242  existExpired = true;
2243  continue;
2244  }
2245 
2246  // currentAbsorb - damage can be absorbed by shield
2247  // If need absorb less damage
2248  if (healing < currentAbsorb + absorbAmount)
2249  currentAbsorb = healing - absorbAmount;
2250 
2251  absorbAmount += currentAbsorb;
2252 
2253  // Reduce shield amount
2254  (*i)->SetAmount((*i)->GetAmount() - currentAbsorb);
2255  // Need remove it later
2256  if ((*i)->GetAmount() <= 0)
2257  existExpired = true;
2258  }
2259 
2260  // Remove all expired absorb auras
2261  if (existExpired)
2262  {
2263  for (AuraEffectList::const_iterator i = vHealAbsorb.begin(); i != vHealAbsorb.end();)
2264  {
2265  AuraEffect* auraEff = *i;
2266  ++i;
2267  if (auraEff->GetAmount() <= 0)
2268  {
2269  uint32 removedAuras = healInfo.GetTarget()->m_removedAurasCount;
2271  if (removedAuras + 1 < healInfo.GetTarget()->m_removedAurasCount)
2272  i = vHealAbsorb.begin();
2273  }
2274  }
2275  }
2276 
2277  if (absorbAmount > 0)
2278  healInfo.AbsorbHeal(absorbAmount);
2279 }
2280 
2281 void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
2282 {
2284  return;
2285 
2286  if (!victim->IsAlive())
2287  return;
2288 
2289  if ((attType == BASE_ATTACK || attType == OFF_ATTACK) && !IsWithinLOSInMap(victim))
2290  return;
2291 
2292  // CombatStart puts the target into stand state, so we need to cache sit state here to know if we should crit later
2293  const bool sittingVictim = victim->GetTypeId() == TYPEID_PLAYER && (victim->IsSitState() || victim->getStandState() == UNIT_STAND_STATE_SLEEP);
2294 
2295  CombatStart(victim);
2297 
2298  if (attType != BASE_ATTACK && attType != OFF_ATTACK)
2299  return; // ignore ranged case
2300 
2301  bool meleeAttack = true;
2302 
2303  // melee attack spell casted at main hand attack only - no normal melee dmg dealt
2304  if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL] && !extra)
2305  {
2306  meleeAttack = false; // The melee attack is replaced by the melee spell
2307 
2308  Spell* meleeSpell = m_currentSpells[CURRENT_MELEE_SPELL];
2309  SpellCastResult castResult = meleeSpell->CheckCast(false);
2310  if (castResult != SPELL_CAST_OK)
2311  {
2312  meleeSpell->SendCastResult(castResult);
2313  meleeSpell->SendInterrupted(0);
2314 
2315  meleeSpell->finish(false);
2316  meleeSpell->SetExecutedCurrently(false);
2317 
2318  if (castResult == SPELL_FAILED_NO_POWER)
2319  {
2320  // Not enough rage, do a regular melee attack instead
2321  meleeAttack = true;
2322  }
2323  }
2324  else
2325  {
2326  meleeSpell->cast(true);
2327  }
2328  }
2329  if (meleeAttack)
2330  {
2331  // attack can be redirected to another target
2332  victim = GetMeleeHitRedirectTarget(victim);
2333  CalcDamageInfo damageInfo;
2334  CalculateMeleeDamage(victim, 0, &damageInfo, attType, sittingVictim);
2335 
2336  // Send log damage message to client
2337  Unit::DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb);
2338  SendAttackStateUpdate(&damageInfo);
2339 
2340  //TriggerAurasProcOnEvent(damageInfo);
2341 
2342  DealMeleeDamage(&damageInfo, true);
2343 
2344  DamageInfo dmgInfo(damageInfo);
2345  ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage,
2346  damageInfo.attackType, nullptr, nullptr, -1, nullptr, &dmgInfo);
2347 
2348  if (GetTypeId() == TYPEID_PLAYER)
2349  LOG_DEBUG("entities.unit", "AttackerStateUpdate: (Player) %s attacked %s for %u dmg, absorbed %u, blocked %u, resisted %u.",
2350  GetGUID().ToString().c_str(), victim->GetGUID().ToString().c_str(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2351  else
2352  LOG_DEBUG("entities.unit", "AttackerStateUpdate: (NPC) %s attacked %s for %u dmg, absorbed %u, blocked %u, resisted %u.",
2353  GetGUID().ToString().c_str(), victim->GetGUID().ToString().c_str(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2354 
2355  // Let the pet know we've started attacking someting. Handles melee attacks only
2356  // Spells such as auto-shot and others handled in WorldSession::HandleCastSpellOpcode
2357  if (GetTypeId() == TYPEID_PLAYER && !m_Controlled.empty())
2358  for (Unit::ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
2359  if (Unit* pet = *itr)
2360  if (pet->IsAlive() && pet->GetTypeId() == TYPEID_UNIT)
2361  pet->ToCreature()->AI()->OwnerAttacked(victim);
2362  }
2363 }
2364 
2366 {
2367  if (!attacker)
2368  {
2369  return false;
2370  }
2371 
2372  AttackerSet attackers = getAttackers();
2373 
2374  if (attackers.size() <= 1) // if the attackers are not more than one
2375  {
2376  return false;
2377  }
2378 
2379  float meleeReach = GetExactDist2d(attacker);
2380  if (meleeReach <= 0)
2381  {
2382  return false;
2383  }
2384 
2385  float minAngle = 0;
2386  Unit *refUnit = nullptr;
2387  uint32 validAttackers = 0;
2388 
2389  double attackerSize = attacker->GetCollisionRadius();
2390 
2391  for (const auto& otherAttacker: attackers)
2392  {
2393  // if the otherAttacker is not valid, skip
2394  if (!otherAttacker || otherAttacker->GetGUID() == attacker->GetGUID() ||
2395  !otherAttacker->IsWithinMeleeRange(this) || otherAttacker->isMoving())
2396  {
2397  continue;
2398  }
2399 
2400  float curretAngle = atan(attacker->GetExactDist2d(otherAttacker) / meleeReach);
2401  if (minAngle == 0 || curretAngle < minAngle)
2402  {
2403  minAngle = curretAngle;
2404  refUnit = otherAttacker;
2405  }
2406 
2407  validAttackers++;
2408  }
2409 
2410  if (!validAttackers || !refUnit)
2411  {
2412  return false;
2413  }
2414 
2415  float contactDist = attackerSize + refUnit->GetCollisionRadius();
2416  float requiredAngle = atan(contactDist / meleeReach);
2417  float attackersAngle = atan(attacker->GetExactDist2d(refUnit) / meleeReach);
2418 
2419  // in instance: the more attacker there are, the higher will be the tollerance
2420  // outside: creatures should not intersecate
2421  float angleTollerance = attacker->GetMap()->IsDungeon() ? requiredAngle - requiredAngle * tanh(validAttackers / 5.0f) : requiredAngle;
2422 
2423  if (attackersAngle > angleTollerance)
2424  {
2425  return false;
2426  }
2427 
2428  double angle = atan(contactDist / meleeReach);
2429 
2430  float angularRadius = frand(0.1f, 0.3f) + angle;
2431  int8 direction = (urand(0, 1) ? -1 : 1);
2432  float currentAngle = GetAngle(refUnit);
2433  float absAngle = currentAngle + angularRadius * direction;
2434 
2435  float x, y, z;
2436  float distance = meleeReach - GetObjectSize();
2437  GetNearPoint(attacker, x, y, z, distance, 0.0f, absAngle);
2438 
2439  if (!GetMap()->CanReachPositionAndGetValidCoords(this, x, y, z, true, true))
2440  {
2441  GetNearPoint(attacker, x, y, z, distance, 0.0f, absAngle * -1); // try the other side
2442 
2443  if (!GetMap()->CanReachPositionAndGetValidCoords(this, x, y, z, true, true))
2444  {
2445  return false;
2446  }
2447  }
2448 
2449  pos.Relocate(x, y, z);
2450 
2451  return true;
2452 }
2453 
2455 {
2456  while (m_extraAttacks)
2457  {
2458  AttackerStateUpdate(victim, BASE_ATTACK, true);
2459  --m_extraAttacks;
2460  }
2461 }
2462 
2464 {
2465  // This is only wrapper
2466 
2467  // Miss chance based on melee
2468  //float miss_chance = MeleeMissChanceCalc(victim, attType);
2469  float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(victim->GetMaxSkillValueForLevel(this)), 0);
2470 
2471  // Critical hit chance
2472  float crit_chance = GetUnitCriticalChance(attType, victim);
2473  if( crit_chance < 0 )
2474  crit_chance = 0;
2475 
2476  float dodge_chance = victim->GetUnitDodgeChance();
2477  float block_chance = victim->GetUnitBlockChance();
2478  float parry_chance = victim->GetUnitParryChance();
2479 
2480  // Useful if want to specify crit & miss chances for melee, else it could be removed
2481  //LOG_DEBUG("entities.unit", "MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance, crit_chance, dodge_chance, parry_chance, block_chance);
2482 
2483  return RollMeleeOutcomeAgainst(victim, attType, int32(crit_chance * 100), int32(miss_chance * 100), int32(dodge_chance * 100), int32(parry_chance * 100), int32(block_chance * 100));
2484 }
2485 
2486 MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const
2487 {
2488  if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())
2489  {
2490  return MELEE_HIT_EVADE;
2491  }
2492 
2493  int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
2494  int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
2495 
2496  int32 attackerWeaponSkill = GetWeaponSkillValue(attType, victim);
2497  int32 victimDefenseSkill = victim->GetDefenseSkillValue(this);
2498 
2499  sScriptMgr->OnBeforeRollMeleeOutcomeAgainst(this, victim, attType, attackerMaxSkillValueForLevel, victimMaxSkillValueForLevel, attackerWeaponSkill, victimDefenseSkill, crit_chance, miss_chance, dodge_chance, parry_chance, block_chance);
2500 
2501  // bonus from skills is 0.04%
2502  int32 skillBonus = 4 * (attackerWeaponSkill - victimMaxSkillValueForLevel);
2503  int32 sum = 0, tmp = 0;
2504  int32 roll = urand (0, 10000);
2505 
2506  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus);
2507  //LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d",
2508  // roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance);
2509 
2510  tmp = miss_chance;
2511 
2512  if (tmp > 0 && roll < (sum += tmp))
2513  {
2514  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: MISS");
2515  return MELEE_HIT_MISS;
2516  }
2517 
2518  // Dodge chance
2519 
2520  // only players can't dodge if attacker is behind
2521  if (victim->GetTypeId() == TYPEID_PLAYER && !victim->HasInArc(M_PI, this) && !victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
2522  {
2523  //LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: attack came from behind and victim was a player.");
2524  }
2525  // Xinef: do not allow to dodge with CREATURE_FLAG_EXTRA_NO_DODGE flag
2527  {
2528  // Reduce dodge chance by attacker expertise rating
2529  if (GetTypeId() == TYPEID_PLAYER)
2530  dodge_chance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100);
2531  else
2532  dodge_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2533 
2534  // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2536  dodge_chance = int32 (float (dodge_chance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
2537 
2538  tmp = dodge_chance;
2539 
2540  // xinef: if casting or stunned - cant dodge
2541  if (victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2542  tmp = 0;
2543 
2544  if ((tmp > 0) // check if unit _can_ dodge
2545  && ((tmp -= skillBonus) > 0)
2546  && roll < (sum += tmp))
2547  {
2548  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum - tmp, sum);
2549  return MELEE_HIT_DODGE;
2550  }
2551  }
2552 
2553  // parry & block chances
2554 
2555  // check if attack comes from behind, nobody can parry or block if attacker is behind
2556  if (!victim->HasInArc(M_PI, this) && !victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION))
2557  {
2558  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: attack came from behind.");
2559  }
2560  else
2561  {
2562  // Reduce parry chance by attacker expertise rating
2563  if (GetTypeId() == TYPEID_PLAYER)
2564  parry_chance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100);
2565  else
2566  parry_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2567 
2569  {
2570  tmp = parry_chance;
2571 
2572  // xinef: cant parry while casting or while stunned
2573  if (victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2574  tmp = 0;
2575 
2576  if (tmp > 0 // check if unit _can_ parry
2577  && (tmp -= skillBonus) > 0
2578  && roll < (sum += tmp))
2579  {
2580  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: PARRY <%d, %d)", sum - tmp, sum);
2581  return MELEE_HIT_PARRY;
2582  }
2583  }
2584 
2586  {
2587  tmp = block_chance;
2588 
2589  // xinef: cant block while casting or while stunned
2590  if (victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2591  tmp = 0;
2592 
2593  if (tmp > 0 // check if unit _can_ block
2594  && (tmp -= skillBonus) > 0
2595  && roll < (sum += tmp))
2596  {
2597  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum - tmp, sum);
2598  return MELEE_HIT_BLOCK;
2599  }
2600  }
2601  }
2602 
2603  // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
2604  if (attType != RANGED_ATTACK &&
2605  (GetTypeId() == TYPEID_PLAYER || IsPet()) &&
2606  victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet() &&
2607  getLevel() < victim->getLevelForTarget(this))
2608  {
2609  // cap possible value (with bonuses > max skill)
2610  int32 skill = attackerWeaponSkill;
2611  int32 maxskill = attackerMaxSkillValueForLevel;
2612  skill = (skill > maxskill) ? maxskill : skill;
2613 
2614  tmp = (10 + (victimDefenseSkill - skill)) * 100;
2615  tmp = tmp > 4000 ? 4000 : tmp;
2616  if (roll < (sum += tmp))
2617  {
2618  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: GLANCING <%d, %d)", sum - 4000, sum);
2619  return MELEE_HIT_GLANCING;
2620  }
2621  }
2622 
2623  // mobs can score crushing blows if they're 4 or more levels above victim
2624  if (getLevelForTarget(victim) >= victim->getLevelForTarget(this) + 4 &&
2625  // can be from by creature (if can) or from controlled player that considered as creature
2626  !IsControlledByPlayer() &&
2627  !(GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSHING_BLOWS))
2628  {
2629  // when their weapon skill is 15 or more above victim's defense skill
2630  tmp = victimDefenseSkill;
2631  int32 tmpmax = victimMaxSkillValueForLevel;
2632  // having defense above your maximum (from items, talents etc.) has no effect
2633  tmp = tmp > tmpmax ? tmpmax : tmp;
2634  // tmp = mob's level * 5 - player's current defense skill
2635  tmp = attackerMaxSkillValueForLevel - tmp;
2636  if (tmp >= 15)
2637  {
2638  // add 2% chance per lacking skill point, min. is 15%
2639  tmp = tmp * 200 - 1500;
2640  if (roll < (sum += tmp))
2641  {
2642  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum - tmp, sum);
2643  return MELEE_HIT_CRUSHING;
2644  }
2645  }
2646  }
2647 
2648  // Critical chance
2649  tmp = crit_chance;
2650 
2651  if (tmp > 0 && roll < (sum += tmp))
2652  {
2653  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum - tmp, sum);
2654  if (GetTypeId() == TYPEID_UNIT && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRIT))
2655  {
2656  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: CRIT DISABLED)");
2657  }
2658  else
2659  return MELEE_HIT_CRIT;
2660  }
2661 
2662  LOG_DEBUG("entities.unit", "RollMeleeOutcomeAgainst: NORMAL");
2663  return MELEE_HIT_NORMAL;
2664 }
2665 
2666 uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
2667 {
2668  float minDamage = 0.0f;
2669  float maxDamage = 0.0f;
2670 
2671  if (normalized || !addTotalPct)
2672  CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage);
2673  else
2674  {
2675  switch (attType)
2676  {
2677  case RANGED_ATTACK:
2680  break;
2681  case BASE_ATTACK:
2682  minDamage = GetFloatValue(UNIT_FIELD_MINDAMAGE);
2683  maxDamage = GetFloatValue(UNIT_FIELD_MAXDAMAGE);
2684  break;
2685  case OFF_ATTACK:
2688  break;
2689  default:
2690  break;
2691  }
2692 
2693  // pussywizard: this check only in "else" section, proper check is also in CalculateMinMaxDamage
2694  if (minDamage > maxDamage)
2695  minDamage = maxDamage;
2696  }
2697 
2698  if (maxDamage == 0.0f)
2699  maxDamage = 5.0f;
2700 
2701  return urand(uint32(minDamage), uint32(maxDamage));
2702 }
2703 
2704 float Unit::CalculateLevelPenalty(SpellInfo const* spellProto) const
2705 {
2706  if (GetTypeId() != TYPEID_PLAYER)
2707  return 1.0f;
2708 
2709  if (spellProto->SpellLevel <= 0 || spellProto->SpellLevel >= spellProto->MaxLevel)
2710  return 1.0f;
2711 
2712  float LvlPenalty = 0.0f;
2713 
2714  // xinef: added brackets
2715  if (spellProto->SpellLevel < 20)
2716  LvlPenalty = (20.0f - spellProto->SpellLevel) * 3.75f;
2717 
2718  float LvlFactor = (float(spellProto->SpellLevel) + 6.0f) / float(getLevel());
2719  if (LvlFactor > 1.0f)
2720  LvlFactor = 1.0f;
2721 
2722  return AddPct(LvlFactor, -LvlPenalty);
2723 }
2724 
2726 {
2728  data << GetGUID();
2729  data << victim->GetGUID();
2730  if (sendTo)
2731  sendTo->SendDirectMessage(&data);
2732  else
2733  SendMessageToSet(&data, true);
2734  LOG_DEBUG("entities.unit", "WORLD: Sent SMSG_ATTACKSTART");
2735 }
2736 
2738 {
2739  // pussywizard: calling SendMeleeAttackStop without clearing UNIT_STATE_MELEE_ATTACKING and then AttackStart the same player may spoil npc rotating!
2740  // pussywizard: this happens in some boss scripts, just add clearing here
2741  // ClearUnitState(UNIT_STATE_MELEE_ATTACKING); // ZOMG! commented out for now
2742 
2743  WorldPacket data(SMSG_ATTACKSTOP, (8 + 8 + 4));
2744  data << GetPackGUID();
2745  data << (victim ? victim->GetPackGUID() : PackedGuid());
2746  data << uint32(0);
2747  SendMessageToSet(&data, true);
2748  LOG_DEBUG("entities.unit", "WORLD: Sent SMSG_ATTACKSTOP");
2749 
2750  if (victim)
2751  LOG_DEBUG("entities.unit", "%s %s stopped attacking %s %s", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUID().ToString().c_str(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUID().ToString().c_str());
2752  else
2753  LOG_DEBUG("entities.unit", "%s %s stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUID().ToString().c_str());
2754 }
2755 
2756 bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
2757 {
2758  // These spells can't be blocked
2759  if (spellProto && spellProto->HasAttribute(SPELL_ATTR0_NO_ACTIVE_DEFENSE))
2760  return false;
2761 
2762  if (victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION) || victim->HasInArc(M_PI, this))
2763  {
2764  // Check creatures flags_extra for disable block
2765  if (victim->GetTypeId() == TYPEID_UNIT &&
2767  return false;
2768 
2769  float blockChance = victim->GetUnitBlockChance();
2770  blockChance += (int32(GetWeaponSkillValue(attackType)) - int32(victim->GetMaxSkillValueForLevel())) * 0.04f;
2771 
2772  // xinef: cant block while casting or while stunned
2773  if (blockChance < 0.0f || victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2774  blockChance = 0.0f;
2775 
2776  if (roll_chance_f(blockChance))
2777  return true;
2778  }
2779  return false;
2780 }
2781 
2783 {
2785  return true;
2786  return false;
2787 }
2788 
2790 {
2791  if (!spell)
2792  return 0;
2793  int32 resist_mech = 0;
2794  for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff)
2795  {
2796  if (!spell->Effects[eff].IsEffect())
2797  break;
2798  int32 effect_mech = spell->GetEffectMechanic(eff);
2799  if (effect_mech)
2800  {
2802  if (resist_mech < temp)
2803  resist_mech = temp;
2804  }
2805  }
2806  return resist_mech;
2807 }
2808 
2809 // Melee based spells hit result calculations
2811 {
2812  // Spells with SPELL_ATTR3_ALWAYS_HIT will additionally fully ignore
2813  // resist and deflect chances
2814  if (spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
2815  return SPELL_MISS_NONE;
2816 
2817  WeaponAttackType attType = BASE_ATTACK;
2818 
2819  // Check damage class instead of attack type to correctly handle judgements
2820  // - they are meele, but can't be dodged/parried/deflected because of ranged dmg class
2821  if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
2822  attType = RANGED_ATTACK;
2823 
2824  int32 attackerWeaponSkill;
2825  // skill value for these spells (for example judgements) is 5* level
2826  if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED && !spellInfo->IsRangedWeaponSpell())
2827  attackerWeaponSkill = getLevel() * 5;
2828  // bonus from skills is 0.04% per skill Diff
2829  else
2830  attackerWeaponSkill = int32(GetWeaponSkillValue(attType, victim));
2831 
2832  int32 skillDiff = attackerWeaponSkill - int32(victim->GetMaxSkillValueForLevel(this));
2833 
2834  uint32 roll = urand (0, 10000);
2835 
2836  uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, skillDiff, spellInfo->Id) * 100.0f);
2837  // Roll miss
2838  uint32 tmp = missChance;
2839  if (roll < tmp)
2840  return SPELL_MISS_MISS;
2841 
2842  bool canDodge = !spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_DODGE);
2843  bool canParry = !spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_PARRY);
2844  bool canBlock = spellInfo->HasAttribute(SPELL_ATTR3_COMPLETELY_BLOCKED) && !spellInfo->HasAttribute(SPELL_ATTR0_CU_DIRECT_DAMAGE);
2845 
2846  // Same spells cannot be parry/dodge
2848  return SPELL_MISS_NONE;
2849 
2850  // Chance resist mechanic
2851  int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
2852  tmp += resist_chance;
2853  if (roll < tmp)
2854  return SPELL_MISS_RESIST;
2855 
2856  // Ranged attacks can only miss, resist and deflect
2857  if (attType == RANGED_ATTACK)
2858  {
2859  // only if in front
2860  if (!victim->HasUnitState(UNIT_STATE_STUNNED) && (victim->HasInArc(M_PI, this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)))
2861  {
2862  int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100;
2863  tmp += deflect_chance;
2864  if (roll < tmp)
2865  return SPELL_MISS_DEFLECT;
2866  }
2867 
2868  canDodge = false;
2869  canParry = false;
2870  }
2871 
2872  // Check for attack from behind
2873  // xinef: if from behind or spell requires cast from behind
2874  if (!victim->HasInArc(M_PI, this) || spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
2875  {
2877  {
2878  // Can`t dodge from behind in PvP (but its possible in PvE)
2879  if (victim->GetTypeId() == TYPEID_PLAYER)
2880  canDodge = false;
2881  // Can`t parry or block
2882  canParry = false;
2883  canBlock = false;
2884  }
2885  }
2886 
2887  // Check creatures flags_extra for disable parry
2888  if (victim->GetTypeId() == TYPEID_UNIT)
2889  {
2890  uint32 flagEx = victim->ToCreature()->GetCreatureTemplate()->flags_extra;
2891  // Xinef: no dodge flag
2892  if (flagEx & CREATURE_FLAG_EXTRA_NO_DODGE)
2893  canDodge = false;
2894  if (flagEx & CREATURE_FLAG_EXTRA_NO_PARRY)
2895  canParry = false;
2896  // Check creatures flags_extra for disable block
2897  if (flagEx & CREATURE_FLAG_EXTRA_NO_BLOCK)
2898  canBlock = false;
2899  }
2900  // Ignore combat result aura
2902  for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
2903  {
2904  if (!(*i)->IsAffectedOnSpell(spellInfo))
2905  continue;
2906  switch ((*i)->GetMiscValue())
2907  {
2908  case MELEE_HIT_DODGE:
2909  canDodge = false;
2910  break;
2911  case MELEE_HIT_BLOCK:
2912  canBlock = false;
2913  break;
2914  case MELEE_HIT_PARRY:
2915  canParry = false;
2916  break;
2917  default:
2918  LOG_DEBUG("entities.unit", "Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT has unhandled state %d", (*i)->GetId(), (*i)->GetMiscValue());
2919  break;
2920  }
2921  }
2922 
2923  if (canDodge)
2924  {
2925  // Roll dodge
2926  int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f) - skillDiff * 4;
2927  // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2929  dodgeChance = int32(float(dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
2930  // Reduce dodge chance by attacker expertise rating
2931  if (GetTypeId() == TYPEID_PLAYER)
2932  dodgeChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2933  else
2934  dodgeChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2935 
2936  // xinef: cant dodge while casting or while stunned
2937  if (dodgeChance < 0 || victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2938  dodgeChance = 0;
2939 
2940  tmp += dodgeChance;
2941  if (roll < tmp)
2942  return SPELL_MISS_DODGE;
2943  }
2944 
2945  if (canParry)
2946  {
2947  // Roll parry
2948  int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f) - skillDiff * 4;
2949  // Reduce parry chance by attacker expertise rating
2950  if (GetTypeId() == TYPEID_PLAYER)
2951  parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2952  else
2953  parryChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2954 
2955  // xinef: cant parry while casting or while stunned
2956  if (parryChance < 0 || victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2957  parryChance = 0;
2958 
2959  tmp += parryChance;
2960  if (roll < tmp)
2961  return SPELL_MISS_PARRY;
2962  }
2963 
2964  if (canBlock)
2965  {
2966  int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f) - skillDiff * 4;
2967 
2968  // xinef: cant block while casting or while stunned
2969  if (blockChance < 0 || victim->IsNonMeleeSpellCast(false, false, true) || victim->HasUnitState(UNIT_STATE_CONTROLLED))
2970  blockChance = 0;
2971 
2972  tmp += blockChance;
2973  if (roll < tmp)
2974  return SPELL_MISS_BLOCK;
2975  }
2976 
2977  return SPELL_MISS_NONE;
2978 }
2979 
2981 {
2982  // Can`t miss on dead target (on skinning for example)
2983  if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER)
2984  return SPELL_MISS_NONE;
2985 
2986  // vehicles cant miss
2987  if (IsVehicle())
2988  return SPELL_MISS_NONE;
2989 
2990  // Spells with SPELL_ATTR3_ALWAYS_HIT will additionally fully ignore
2991  // resist and deflect chances
2992  // xinef: skip all calculations, proof: Toxic Tolerance quest
2993  if (spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
2994  return SPELL_MISS_NONE;
2995 
2996  if (spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_MISS))
2997  {
2998  return SPELL_MISS_NONE;
2999  }
3000 
3001  SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
3002  // PvP - PvE spell misschances per leveldif > 2
3003  int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
3004  int32 thisLevel = getLevelForTarget(victim);
3005  if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
3006  thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
3007  int32 leveldif = int32(victim->getLevelForTarget(this)) - thisLevel;
3008 
3009  // Base hit chance from attacker and victim levels
3010  int32 modHitChance;
3011  if (leveldif < 3)
3012  modHitChance = 96 - leveldif;
3013  else
3014  modHitChance = 94 - (leveldif - 2) * lchance;
3015 
3016  // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
3017  if (Player* modOwner = GetSpellModOwner())
3018  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
3019 
3020  // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
3022 
3023  // Spells with SPELL_ATTR3_ALWAYS_HIT will ignore target's avoidance effects
3024  // xinef: imo it should completly ignore all calculations, eg: 14792. Hits 80 level players on blizz without any problems
3025  //if (!spell->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
3026  {
3027  // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
3028  modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
3029  // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
3030  if (spellInfo->IsAffectingArea())
3031  modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
3032 
3033  // Decrease hit chance from victim rating bonus
3034  if (victim->GetTypeId() == TYPEID_PLAYER)
3035  modHitChance -= int32(victim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
3036  }
3037 
3038  int32 HitChance = modHitChance * 100;
3039  // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
3040  // Xinef: Totems should inherit casters ratings?
3041  if (IsTotem())
3042  {
3043  if (Unit* owner = GetOwner())
3044  HitChance += int32(owner->m_modSpellHitChance * 100.0f);
3045  }
3046  else
3047  HitChance += int32(m_modSpellHitChance * 100.0f);
3048 
3049  if (HitChance < 100)
3050  HitChance = 100;
3051  else if (HitChance > 10000)
3052  HitChance = 10000;
3053 
3054  int32 tmp = 10000 - HitChance;
3055 
3056  int32 rand = irand(1, 10000); // Needs to be 1 to 10000 to avoid the 1/10000 chance to miss on 100% hit rating
3057 
3058  if (rand < tmp)
3059  return SPELL_MISS_MISS;
3060 
3061  // Chance resist mechanic (select max value from every mechanic spell effect)
3062  int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
3063  tmp += resist_chance;
3064 
3065  // Chance resist debuff
3066  if (!spellInfo->IsPositive() && !spellInfo->HasAttribute(SPELL_ATTR4_NO_CAST_LOG))
3067  {
3068  bool bNegativeAura = true;
3069  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
3070  {
3071  // Xinef: Check if effect exists!
3072  if (spellInfo->Effects[i].IsEffect() && spellInfo->Effects[i].ApplyAuraName == 0)
3073  {
3074  bNegativeAura = false;
3075  break;
3076  }
3077  }
3078 
3079  if (bNegativeAura)
3080  {
3083  }
3084 
3085  // Players resistance for binary spells
3087  tmp += int32(Unit::GetEffectiveResistChance(this, spellInfo->GetSchoolMask(), victim, spellInfo) * 10000.0f); // 100 for spell calculations, and 100 for return value percentage
3088  }
3089 
3090  // Roll chance
3091  if (rand < tmp)
3092  return SPELL_MISS_RESIST;
3093 
3094  // cast by caster in front of victim
3095  if (!victim->HasUnitState(UNIT_STATE_STUNNED) && (victim->HasInArc(M_PI, this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)))
3096  {
3097  int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100;
3098  tmp += deflect_chance;
3099  if (rand < tmp)
3100  return SPELL_MISS_DEFLECT;
3101  }
3102 
3103  return SPELL_MISS_NONE;
3104 }
3105 
3106 // Calculate spell hit result can be:
3107 // Every spell can: Evade/Immune/Reflect/Sucesful hit
3108 // For melee based spells:
3109 // Miss
3110 // Dodge
3111 // Parry
3112 // For spells
3113 // Resist
3114 SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool CanReflect)
3115 {
3116  // Check for immune
3117  if (victim->IsImmunedToSpell(spell))
3118  return SPELL_MISS_IMMUNE;
3119 
3120  // All positive spells can`t miss
3121  // TODO: client not show miss log for this spells - so need find info for this in dbc and use it!
3122  if ((spell->IsPositive() || spell->HasEffect(SPELL_EFFECT_DISPEL))
3123  && (!IsHostileTo(victim))) // prevent from affecting enemy by "positive" spell
3124  return SPELL_MISS_NONE;
3125 
3126  // Check for immune
3127  // xinef: check for school immunity only
3128  if (victim->IsImmunedToSchool(spell))
3129  return SPELL_MISS_IMMUNE;
3130 
3131  if (this == victim)
3132  return SPELL_MISS_NONE;
3133 
3134  // Return evade for units in evade mode
3135  if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE))
3136  return SPELL_MISS_EVADE;
3137 
3138  // Try victim reflect spell
3139  if (CanReflect)
3140  {
3141  int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
3142  Unit::AuraEffectList const& mReflectSpellsSchool = victim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL);
3143  for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
3144  if ((*i)->GetMiscValue() & spell->GetSchoolMask())
3145  reflectchance += (*i)->GetAmount();
3146  if (reflectchance > 0 && roll_chance_i(reflectchance))
3147  {
3148  // Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
3149  //ProcDamageAndSpell(victim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, spell);
3150  return SPELL_MISS_REFLECT;
3151  }
3152  }
3153 
3154  switch (spell->DmgClass)
3155  {
3158  return MeleeSpellHitResult(victim, spell);
3160  {
3161  if (spell->SpellFamilyName)
3162  {
3163  return SPELL_MISS_NONE;
3164  }
3165  // Xinef: apply DAMAGE_CLASS_MAGIC conditions to damaging DAMAGE_CLASS_NONE spells
3166  for (uint8 i = EFFECT_0; i < MAX_SPELL_EFFECTS; ++i)
3167  if (spell->Effects[i].Effect && spell->Effects[i].Effect != SPELL_EFFECT_SCHOOL_DAMAGE)
3168  if (spell->Effects[i].ApplyAuraName != SPELL_AURA_PERIODIC_DAMAGE)
3169  return SPELL_MISS_NONE;
3170  [[fallthrough]];
3171  }
3173  return MagicSpellHitResult(victim, spell);
3174  }
3175  return SPELL_MISS_NONE;
3176 }
3177 
3179 {
3180  if (GetTypeId() == TYPEID_PLAYER)
3181  {
3182  // in PvP use full skill instead current skill value
3183  uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER)
3186  value += uint32(ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
3187  return value;
3188  }
3189  else
3190  return GetUnitMeleeSkill(target);
3191 }
3192 
3194 {
3195  if (GetTypeId() == TYPEID_PLAYER)
3196  return ToPlayer()->GetRealDodge(); //GetFloatValue(PLAYER_DODGE_PERCENTAGE);
3197  else
3198  {
3199  if (ToCreature()->IsTotem())
3200  return 0.0f;
3201  else
3202  {
3203  float dodge = ToCreature()->isWorldBoss() ? 5.85f : 5.0f; // Xinef: bosses should have 6.5% dodge (5.9 + 0.6 from defense skill difference)
3205  return dodge > 0.0f ? dodge : 0.0f;
3206  }
3207  }
3208 }
3209 
3211 {
3212  float chance = 0.0f;
3213 
3214  if (Player const* player = ToPlayer())
3215  {
3216  if (player->CanParry())
3217  {
3218  Item* tmpitem = player->GetWeaponForAttack(BASE_ATTACK, true);
3219  if (!tmpitem)
3220  tmpitem = player->GetWeaponForAttack(OFF_ATTACK, true);
3221 
3222  if (tmpitem)
3223  chance = player->GetRealParry(); //GetFloatValue(PLAYER_PARRY_PERCENTAGE);
3224  }
3225  }
3226  else if (GetTypeId() == TYPEID_UNIT)
3227  {
3228  if (ToCreature()->isWorldBoss())
3229  chance = 13.4f; // + 0.6 by skill diff
3231  chance = 5.0f;
3232 
3233  // Xinef: if aura is present, type should not matter
3235  }
3236 
3237  return chance > 0.0f ? chance : 0.0f;
3238 }
3239 
3241 {
3242  float miss_chance = 5.00f;
3243 
3244  if (Player const* player = ToPlayer())
3245  miss_chance += player->GetMissPercentageFromDefence();
3246 
3247  if (attType == RANGED_ATTACK)
3249  else
3251 
3252  return miss_chance;
3253 }
3254 
3256 {
3257  if (Player const* player = ToPlayer())
3258  {
3259  if (player->CanBlock())
3260  {
3261  Item* tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
3262  if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetTemplate()->Block)
3264  }
3265  // is player but has no block ability or no not broken shield equipped
3266  return 0.0f;
3267  }
3268  else
3269  {
3270  if (ToCreature()->IsTotem())
3271  return 0.0f;
3272  else
3273  {
3274  float block = 5.0f;
3276  return block > 0.0f ? block : 0.0f;
3277  }
3278  }
3279 }
3280 
3281 float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const
3282 {
3283  float crit;
3284 
3285  if (GetTypeId() == TYPEID_PLAYER)
3286  {
3287  switch (attackType)
3288  {
3289  case BASE_ATTACK:
3291  break;
3292  case OFF_ATTACK:
3294  break;
3295  case RANGED_ATTACK:
3297  break;
3298  // Just for good manner
3299  default:
3300  crit = 0.0f;
3301  break;
3302  }
3303  }
3304  else
3305  {
3306  crit = 5.0f;
3309  }
3310 
3311  // flat aura mods
3312  if (attackType == RANGED_ATTACK)
3314  else
3316 
3318  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3319  {
3320  if (GetGUID() != (*i)->GetCasterGUID())
3321  continue;
3322 
3323  crit += (*i)->GetAmount();
3324  }
3325 
3326  // reduce crit chance from Rating for players
3327  if (attackType != RANGED_ATTACK)
3328  Unit::ApplyResilience(victim, &crit, nullptr, false, CR_CRIT_TAKEN_MELEE);
3329  else
3330  Unit::ApplyResilience(victim, &crit, nullptr, false, CR_CRIT_TAKEN_RANGED);
3331 
3332  // Apply crit chance from defence skill
3333  crit += (int32(GetMaxSkillValueForLevel(victim)) - int32(victim->GetDefenseSkillValue(this))) * 0.04f;
3334 
3335  // xinef: SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE should be calculated at the end
3337 
3338  if (crit < 0.0f)
3339  crit = 0.0f;
3340  return crit;
3341 }
3342 
3344 {
3345  uint32 value = 0;
3346  if (Player const* player = ToPlayer())
3347  {
3348  Item* item = player->GetWeaponForAttack(attType, true);
3349 
3350  // feral or unarmed skill only for base attack
3351  if (attType != BASE_ATTACK && !item)
3352  return 0;
3353 
3354  if (IsInFeralForm())
3355  return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
3356 
3357  // weapon skill or (unarmed for base attack)
3358  uint32 skill = SKILL_UNARMED;
3359  if (item)
3360  skill = item->GetSkill();
3361 
3362  // in PvP use full skill instead current skill value
3363  value = (target && target->IsControlledByPlayer())
3364  ? player->GetMaxSkillValue(skill)
3365  : player->GetSkillValue(skill);
3366  // Modify value from ratings
3367  value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL));
3368  switch (attType)
3369  {
3370  case BASE_ATTACK:
3371  value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND));
3372  break;
3373  case OFF_ATTACK:
3374  value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND));
3375  break;
3376  case RANGED_ATTACK:
3377  value += uint32(player->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED));
3378  break;
3379  default:
3380  break;
3381  }
3382  }
3383  else
3384  value = GetUnitMeleeSkill(target);
3385  return value;
3386 }
3387 
3389 {
3390  while (!m_removedAuras.empty())
3391  {
3392  delete m_removedAuras.front();
3393  m_removedAuras.pop_front();
3394  }
3395 }
3396 
3398 {
3401 
3402  // remove finished spells from current pointers
3403  for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
3404  {
3405  if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED)
3406  {
3408  m_currentSpells[i] = nullptr; // remove pointer
3409  }
3410  }
3411 
3412  // m_auraUpdateIterator can be updated in indirect called code at aura remove to skip next planned to update but removed auras
3414  {
3415  Aura* i_aura = m_auraUpdateIterator->second;
3416  ++m_auraUpdateIterator; // need shift to next for allow update if need into aura update
3417  i_aura->UpdateOwner(time, this);
3418  }
3419 
3420  // remove expired auras - do that after updates(used in scripts?)
3421  for (AuraMap::iterator i = m_ownedAuras.begin(); i != m_ownedAuras.end();)
3422  {
3423  if (i->second->IsExpired())
3425  else
3426  ++i;
3427  }
3428 
3429  for (VisibleAuraMap::iterator itr = m_visibleAuras.begin(); itr != m_visibleAuras.end(); ++itr)
3430  if (itr->second->IsNeedClientUpdate())
3431  itr->second->ClientUpdate();
3432 
3434 
3435  if (!m_gameObj.empty())
3436  {
3437  for (GameObjectList::iterator itr = m_gameObj.begin(); itr != m_gameObj.end();)
3438  {
3439  if (GameObject* go = ObjectAccessor::GetGameObject(*this, *itr))
3440  if (!go->isSpawned())
3441  {
3442  go->SetOwnerGUID(ObjectGuid::Empty);
3443  go->SetRespawnTime(0);
3444  go->Delete();
3445  m_gameObj.erase(itr++);
3446  continue;
3447  }
3448  ++itr;
3449  }
3450  }
3451 }
3452 
3454 {
3455  SpellInfo const* spellProto = nullptr;
3457  {
3459  }
3460 
3461  if (!spellProto)
3462  {
3463  return;
3464  }
3465 
3466  static uint32 const HUNTER_AUTOSHOOT = 75;
3467 
3468  // Check "realtime" interrupts
3469  if ((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving() && spellProto->Id != HUNTER_AUTOSHOOT) || IsNonMeleeSpellCast(false, false, true, spellProto->Id == HUNTER_AUTOSHOOT))
3470  {
3471  // cancel wand shoot
3472  if (spellProto->Id != HUNTER_AUTOSHOOT)
3474  m_AutoRepeatFirstCast = true;
3475  return;
3476  }
3477 
3478  // Apply delay (Hunter's autoshoot not affected)
3479  if (m_AutoRepeatFirstCast && getAttackTimer(RANGED_ATTACK) < 500 && spellProto->Id != HUNTER_AUTOSHOOT)
3480  {
3482  }
3483 
3484  m_AutoRepeatFirstCast = false;
3485 
3486  // Check for ranged attack timer
3488  {
3490  if (result != SPELL_CAST_OK)
3491  {
3492  if (spellProto->Id != HUNTER_AUTOSHOOT)
3493  {
3495  }
3496 
3497  return;
3498  }
3499 
3500  // We want to shoot
3501  Spell* spell = new Spell(this, spellProto, TRIGGERED_FULL_MASK);
3502  spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets));
3503 
3504  // Reset attack
3506  }
3507 }
3508 
3510 {
3511  ASSERT(pSpell); // nullptr may be never passed here, use InterruptSpell or InterruptNonMeleeSpells
3512 
3513  CurrentSpellTypes CSpellType = pSpell->GetCurrentContainer();
3514 
3515  if (pSpell == m_currentSpells[CSpellType]) // avoid breaking self
3516  return;
3517 
3518  // break same type spell if it is not delayed
3519  InterruptSpell(CSpellType, false);
3520 
3521  // special breakage effects:
3522  switch (CSpellType)
3523  {
3524  case CURRENT_GENERIC_SPELL:
3525  {
3526  // generic spells always break channeled not delayed spells
3528  if (s->GetSpellInfo()->Id != 69051) // pussywizard: FoS, boss Devourer of Souls, Mirrored Soul, does not have any special attribute
3530 
3531  // autorepeat breaking
3533  {
3534  // break autorepeat if not Auto Shot
3535  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75)
3537  m_AutoRepeatFirstCast = true;
3538  }
3539  if (pSpell->GetCastTime() > 0)
3541 
3542  break;
3543  }
3545  {
3546  // channel spells always break generic non-delayed and any channeled spells
3549 
3550  // it also does break autorepeat if not Auto Shot
3552  m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != 75)
3555 
3556  break;
3557  }
3559  {
3560  // only Auto Shoot does not break anything
3561  if (pSpell->m_spellInfo->Id != 75)
3562  {
3563  // generic autorepeats break generic non-delayed and channeled non-delayed spells
3566  }
3567  // special action: set first cast flag
3568  m_AutoRepeatFirstCast = true;
3569 
3570  break;
3571  }
3572 
3573  default:
3574  // other spell types don't break anything now
3575  break;
3576  }
3577 
3578  // current spell (if it is still here) may be safely deleted now
3579  if (m_currentSpells[CSpellType])
3580  m_currentSpells[CSpellType]->SetReferencedFromCurrent(false);
3581 
3582  // set new current spell
3583  m_currentSpells[CSpellType] = pSpell;
3584  pSpell->SetReferencedFromCurrent(true);
3585 
3586  pSpell->m_selfContainer = &(m_currentSpells[pSpell->GetCurrentContainer()]);
3587 }
3588 
3589 void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool withInstant, bool bySelf)
3590 {
3591  //LOG_DEBUG("entities.unit", "Interrupt spell for unit %u.", GetEntry());
3592  Spell* spell = m_currentSpells[spellType];
3593  if (spell
3594  && (withDelayed || spell->getState() != SPELL_STATE_DELAYED)
3595  && (withInstant || spell->GetCastTime() > 0 || spell->getState() == SPELL_STATE_CASTING)) // xinef: or spell is in casting state (channeled spells only)
3596  {
3597  // for example, do not let self-stun aura interrupt itself
3598  if (!spell->IsInterruptable())
3599  return;
3600 
3601  // send autorepeat cancel message for autorepeat spells
3602  if (spellType == CURRENT_AUTOREPEAT_SPELL)
3603  if (GetTypeId() == TYPEID_PLAYER)
3604  ToPlayer()->SendAutoRepeatCancel(this);
3605 
3606  if (spell->getState() != SPELL_STATE_FINISHED)
3607  spell->cancel(bySelf);
3608 
3609  m_currentSpells[spellType] = nullptr;
3610  spell->SetReferencedFromCurrent(false);
3611  }
3612 }
3613 
3614 void Unit::FinishSpell(CurrentSpellTypes spellType, bool ok /*= true*/)
3615 {
3616  Spell* spell = m_currentSpells[spellType];
3617  if (!spell)
3618  return;
3619 
3620  if (spellType == CURRENT_CHANNELED_SPELL)
3621  spell->SendChannelUpdate(0);
3622 
3623  spell->finish(ok);
3624 }
3625 
3626 bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAutorepeat, bool isAutoshoot, bool skipInstant) const
3627 {
3628  // We don't do loop here to explicitly show that melee spell is excluded.
3629  // Maybe later some special spells will be excluded too.
3630 
3631  // generic spells are cast when they are not finished and not delayed
3634  (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED))
3635  {
3636  if (!skipInstant || m_currentSpells[CURRENT_GENERIC_SPELL]->GetCastTime())
3637  {
3638  if (!isAutoshoot || !m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS))
3639  return true;
3640  }
3641  }
3642  // channeled spells may be delayed, but they are still considered cast
3643  if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] &&
3645  {
3646  if (!isAutoshoot || !m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS))
3647  return true;
3648  }
3649  // autorepeat spells may be finished or delayed, but they are still considered cast
3650  if (!skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
3651  return true;
3652 
3653  return false;
3654 }
3655 
3656 void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id, bool withInstant, bool bySelf)
3657 {
3658  // generic spells are interrupted if they are not finished or delayed
3659  if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id == spell_id))
3660  InterruptSpell(CURRENT_GENERIC_SPELL, withDelayed, withInstant, bySelf);
3661 
3662  // autorepeat spells are interrupted if they are not finished or delayed
3663  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == spell_id))
3664  InterruptSpell(CURRENT_AUTOREPEAT_SPELL, withDelayed, withInstant, bySelf);
3665 
3666  // channeled spells are interrupted if they are not finished, even if they are delayed
3667  if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id == spell_id))
3668  InterruptSpell(CURRENT_CHANNELED_SPELL, true, true, bySelf);
3669 }
3670 
3672 {
3673  for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
3674  if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id == spell_id)
3675  return m_currentSpells[i];
3676  return nullptr;
3677 }
3678 
3680 {
3681  if (Spell const* spell = FindCurrentSpellBySpellId(spell_id))
3682  return spell->GetCastTime();
3683  return 0;
3684 }
3685 
3687 {
3688  // can always move when not casting
3690  {
3691  return false;
3692  }
3693 
3694  // channeled spells during channel stage (after the initial cast timer) allow movement with a specific spell attribute
3696  {
3697  if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
3698  {
3699  if (spell->GetSpellInfo()->IsMoveAllowedChannel())
3700  {
3701  return false;
3702  }
3703  }
3704  }
3705 
3706  // prohibit movement for all other spell casts
3707  return true;
3708 }
3709 
3711 {
3713  if (spell->getState() != SPELL_STATE_FINISHED)
3714  return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL) && spell->IsChannelActive();
3715 
3716  return false;
3717 }
3718 
3719 bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
3720 {
3721  return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
3722 }
3723 
3724 bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
3725 {
3726  return IsWithinDistInMap(target, distance) && !HasInArc(2 * M_PI - arc, target);
3727 }
3728 
3730 {
3731  if (c->GetMapId() == 618) // Ring of Valor
3732  {
3733  // skip transport check, check for being below floor level
3734  if (this->GetPositionZ() < 28.0f)
3735  return false;
3736  if (BattlegroundMap* bgMap = c->GetMap()->ToBattlegroundMap())
3737  if (Battleground* bg = bgMap->GetBG())
3738  if (bg->GetStartTime() < 80133) // 60000ms preparation time + 20133ms elevator rise time
3739  return false;
3740  }
3741  else if (c->GetMapId() == 631) // Icecrown Citadel
3742  {
3743  // if static transport doesn't match - return false
3744  if (c->GetTransport() != this->GetTransport() && ((c->GetTransport() && c->GetTransport()->IsStaticTransport()) || (this->GetTransport() && this->GetTransport()->IsStaticTransport())))
3745  return false;
3746 
3747  // special handling for ICC (map 631), for non-flying pets in Gunship Battle, for trash npcs this is done via CanAIAttack
3748  if (c->GetOwnerGUID().IsPlayer() && !c->CanFly())
3749  {
3750  if (c->GetTransport() != this->GetTransport())
3751  return false;
3752  if (this->GetTransport())
3753  {
3754  if (c->GetPositionY() < 2033.0f)
3755  {
3756  if (this->GetPositionY() > 2033.0f)
3757  return false;
3758  }
3759  else if (c->GetPositionY() < 2438.0f)
3760  {
3761  if (this->GetPositionY() < 2033.0f || this->GetPositionY() > 2438.0f)
3762  return false;
3763  }
3764  else if (this->GetPositionY() < 2438.0f)
3765  return false;
3766  }
3767  }
3768  }
3769  else
3770  {
3771  // pussywizard: prevent any bugs by passengers exiting transports or normal creatures flying away
3772  if (c->GetTransport() != this->GetTransport())
3773  return false;
3774  }
3775 
3776  if (IsInWater())
3777  return IsUnderWater() ? c->CanEnterWater() : (c->CanEnterWater() || c->CanFly());
3778  else
3779  return c->CanWalk() || c->CanFly() || (c->CanSwim() && IsInWater());
3780 }
3781 
3783 {
3786 }
3787 
3789 {
3790  if (GetTypeId() == TYPEID_UNIT)
3792 
3793  if (IsFlying() || (!IsControlledByPlayer()))
3794  return;
3795 
3796  LiquidData const& liquidData = GetLiquidData();
3797 
3798  // remove appropriate auras if we are swimming/not swimming respectively
3799  if (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING)
3801  else
3803 
3804  // liquid aura handling
3805  LiquidTypeEntry const* curLiquid = nullptr;
3806  if ((liquidData.Status & MAP_LIQUID_STATUS_SWIMMING))
3807  curLiquid = sLiquidTypeStore.LookupEntry(liquidData.Entry);
3808 
3809  if (curLiquid != _lastLiquid)
3810  {
3813 
3814  // Set _lastLiquid before casting liquid spell to avoid infinite loops
3815  _lastLiquid = curLiquid;
3816 
3818  if (curLiquid && curLiquid->SpellId && (!player || !player->IsGameMaster()))
3819  CastSpell(this, curLiquid->SpellId, true);
3820  }
3821 }
3822 
3824 {
3825  if (ptr != defaultValue && ptr) ptr->RemovePointedBy(this);
3826  ptr = defaultValue;
3827 }
3828 
3830 {
3831  if (ptr != defaultValue && ptr) ptr->RemovePointedBy(this);
3832  ptr = u;
3833  if (ptr != defaultValue && ptr) ptr->AddPointedBy(this);
3834 }
3835 
3837 {
3838  LOG_INFO("misc", "SafeUnitPointer::UnitDeleted !!!");
3839  if (defaultValue)
3840  {
3841  if (Player* p = defaultValue->ToPlayer())
3842  {
3843  LOG_INFO("misc", "SafeUnitPointer::UnitDeleted (A1) - %s, %u, %u, %u, %u, %u, %u, %u",
3844  p->GetGUID().ToString().c_str(), p->GetMapId(), p->GetInstanceId(), p->FindMap()->GetId(), p->IsInWorld() ? 1 : 0, p->IsDuringRemoveFromWorld() ? 1 : 0, p->IsBeingTeleported() ? 1 : 0, p->isBeingLoaded() ? 1 : 0);
3845  if (ptr)
3846  LOG_INFO("misc", "SafeUnitPointer::UnitDeleted (A2)");
3847 
3848  p->GetSession()->KickPlayer("Unit deleted");
3849  }
3850  }
3851  else if (ptr)
3852  LOG_INFO("misc", "SafeUnitPointer::UnitDeleted (B1)");
3853 
3854  ptr = defaultValue;
3855 }
3856 
3858 {
3859  if (thisUnit->SafeUnitPointerSet.empty())
3860  return;
3861  for (std::set<SafeUnitPointer*>::iterator itr = thisUnit->SafeUnitPointerSet.begin(); itr != thisUnit->SafeUnitPointerSet.end(); ++itr)
3862  (*itr)->UnitDeleted();
3863 
3864  thisUnit->SafeUnitPointerSet.clear();
3865 }
3866 
3867 bool Unit::IsInWater() const
3868 {
3869  return (GetLiquidData().Status & MAP_LIQUID_STATUS_SWIMMING) != 0;
3870 }
3871 
3873 {
3875 }
3876 
3878 {
3880 }
3881 
3882 Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount /*= nullptr*/, Item* castItem /*= nullptr*/, ObjectGuid casterGUID /*= ObjectGuid::Empty*/, bool periodicReset /*= false*/)
3883 {
3884  ASSERT(casterGUID || caster);
3885  if (!casterGUID)
3886  casterGUID = caster->GetGUID();
3887 
3888  // Xinef: Hax for mixology, best solution qq
3889  if (sSpellMgr->GetSpellGroup(newAura->Id) == 1)
3890  return nullptr;
3891 
3892  // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times
3893  if (!newAura->IsMultiSlotAura())
3894  {
3895  // check if cast item changed
3896  ObjectGuid castItemGUID;
3897  if (castItem)
3898  castItemGUID = castItem->GetGUID();
3899 
3900  // find current aura from spell and change it's stackamount, or refresh it's duration
3901  if (Aura* foundAura = GetOwnedAura(newAura->Id, newAura->HasAttribute(SPELL_ATTR0_CU_SINGLE_AURA_STACK) ? ObjectGuid::Empty : casterGUID, newAura->HasAttribute(SPELL_ATTR0_CU_ENCHANT_PROC) ? castItemGUID : ObjectGuid::Empty, 0))
3902  {
3903  // effect masks do not match
3904  // extremely rare case
3905  // let's just recreate aura
3906  if (effMask != foundAura->GetEffectMask())
3907  return nullptr;
3908 
3909  // update basepoints with new values - effect amount will be recalculated in ModStackAmount
3910  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
3911  {
3912  if (!foundAura->HasEffect(i))
3913  continue;
3914 
3915  int bp;
3916  if (baseAmount)
3917  bp = *(baseAmount + i);
3918  else
3919  bp = foundAura->GetSpellInfo()->Effects[i].BasePoints;
3920 
3921  int32* oldBP = const_cast<int32*>(&(foundAura->GetEffect(i)->m_baseAmount));
3922  *oldBP = bp;
3923  }
3924 
3925  // correct cast item guid if needed
3926  if (castItemGUID != foundAura->GetCastItemGUID())
3927  {
3928  ObjectGuid* oldGUID = const_cast<ObjectGuid*>(&foundAura->m_castItemGuid);
3929  *oldGUID = castItemGUID;
3930  }
3931 
3932  // try to increase stack amount
3933  foundAura->ModStackAmount(1, AURA_REMOVE_BY_DEFAULT, periodicReset);
3934  return foundAura;
3935  }
3936  }
3937 
3938  return nullptr;
3939 }
3940 
3941 void Unit::_AddAura(UnitAura* aura, Unit* caster)
3942 {
3944  m_ownedAuras.insert(AuraMap::value_type(aura->GetId(), aura));
3945 
3947 
3948  if (aura->IsRemoved())
3949  return;
3950 
3952  if (aura->IsSingleTarget())
3953  {
3954  ASSERT((IsInWorld() && !IsDuringRemoveFromWorld()) || (aura->GetCasterGUID() == GetGUID()));
3955  /* @HACK: Player is not in world during loading auras.
3956  * Single target auras are not saved or loaded from database
3957  * but may be created as a result of aura links (player mounts with passengers)
3958  */
3959 
3960  // register single target aura
3961  caster->GetSingleCastAuras().push_back(aura);
3962  // remove other single target auras
3963  Unit::AuraList& scAuras = caster->GetSingleCastAuras();
3964  for (Unit::AuraList::iterator itr = scAuras.begin(); itr != scAuras.end();)
3965  {
3966  if ((*itr) != aura &&
3967  (*itr)->IsSingleTargetWith(aura))
3968  {
3969  (*itr)->Remove();
3970  itr = scAuras.begin();
3971  }
3972  else
3973  ++itr;
3974  }
3975  }
3976 }
3977 
3978 // creates aura application instance and registers it in lists
3979 // aura application effects are handled separately to prevent aura list corruption
3981 {
3982  // can't apply aura on unit which is going to be deleted - to not create a memory leak
3984  // aura musn't be removed
3985  ASSERT(!aura->IsRemoved());
3986 
3987  // aura mustn't be already applied on target
3988  ASSERT (!aura->IsAppliedOnTarget(GetGUID()) && "Unit::_CreateAuraApplication: aura musn't be applied on target");
3989 
3990  SpellInfo const* aurSpellInfo = aura->GetSpellInfo();
3991  uint32 aurId = aurSpellInfo->Id;
3992 
3993  // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
3994  // Xinef: Added IsAllowingDeadTarget check
3995  if (!IsAlive() && !aurSpellInfo->IsDeathPersistent() && !aurSpellInfo->IsAllowingDeadTarget() && (GetTypeId() != TYPEID_PLAYER || !ToPlayer()->GetSession()->PlayerLoading()))
3996  return nullptr;
3997 
3998  Unit* caster = aura->GetCaster();
3999 
4000  AuraApplication* aurApp = new AuraApplication(this, caster, aura, effMask);
4001  m_appliedAuras.insert(AuraApplicationMap::value_type(aurId, aurApp));
4002 
4003  // xinef: do not insert our application to interruptible list if application target is not the owner (area auras)
4004  // xinef: even if it gets removed, it will be reapplied in a second
4005  if (aurSpellInfo->AuraInterruptFlags && this == aura->GetOwner())
4006  {
4007  m_interruptableAuras.push_back(aurApp);
4008  AddInterruptMask(aurSpellInfo->AuraInterruptFlags);
4009  }
4010 
4011  if (AuraStateType aState = aura->GetSpellInfo()->GetAuraState())
4012  m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, aurApp));
4013 
4014  aura->_ApplyForTarget(this, caster, aurApp);
4015  return aurApp;
4016 }
4017 
4018 void Unit::_ApplyAuraEffect(Aura* aura, uint8 effIndex)
4019 {
4020  ASSERT(aura);
4021  ASSERT(aura->HasEffect(effIndex));
4022  AuraApplication* aurApp = aura->GetApplicationOfTarget(GetGUID());
4023  ASSERT(aurApp);
4024  if (!aurApp->GetEffectMask())
4025  _ApplyAura(aurApp, 1 << effIndex);
4026  else
4027  aurApp->_HandleEffect(effIndex, true);
4028 }
4029 
4030 // handles effects of aura application
4031 // should be done after registering aura in lists
4033 {
4034  Aura* aura = aurApp->GetBase();
4035 
4037 
4038  if (aurApp->GetRemoveMode())
4039  return;
4040 
4041  Unit* caster = aura->GetCaster();
4042 
4043  // Update target aura state flag
4044  const SpellInfo* spellInfo = aura->GetSpellInfo();
4045  if (AuraStateType aState = spellInfo->GetAuraState())
4046  {
4047  if (aState != AURA_STATE_CONFLAGRATE)
4048  {
4049  // Sting (hunter's pet ability), Faerie Fire (druid versions)
4050  if (aState == AURA_STATE_FAERIE_FIRE)
4052 
4053  ModifyAuraState(aState, true);
4054  }
4055  else if (caster)
4056  {
4058  m_Events.AddEvent(pEvent, m_Events.CalculateTime(700)); // intended 700ms delay before allowing to cast conflagrate
4059  }
4060  }
4061 
4062  if (aurApp->GetRemoveMode())
4063  return;
4064 
4065  // Sitdown on apply aura req seated
4068 
4069  if (aurApp->GetRemoveMode())
4070  return;
4071 
4072  aura->HandleAuraSpecificMods(aurApp, caster, true, false);
4073 
4074  // apply effects of the aura
4075  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
4076  {
4077  if (effMask & 1 << i && (!aurApp->GetRemoveMode()))
4078  aurApp->_HandleEffect(i, true);
4079  }
4080 }
4081 
4082 // removes aura application from lists and unapplies effects
4083 void Unit::_UnapplyAura(AuraApplicationMap::iterator& i, AuraRemoveMode removeMode)
4084 {
4085  AuraApplication* aurApp = i->second;
4086  ASSERT(aurApp);
4087  ASSERT(!aurApp->GetRemoveMode());
4088  ASSERT(aurApp->GetTarget() == this);
4089 
4090  aurApp->SetRemoveMode(removeMode);
4091  Aura* aura = aurApp->GetBase();
4092  LOG_DEBUG("spells.aura", "Aura %u now is remove mode %d", aura->GetId(), removeMode);
4093 
4094  // dead loop is killing the server probably
4095  ASSERT(m_removedAurasCount < 0xFFFFFFFF);
4096 
4098 
4099  Unit* caster = aura->GetCaster();
4100 
4101  // Remove all pointers from lists here to prevent possible pointer invalidation on spellcast/auraapply/auraremove
4102  m_appliedAuras.erase(i);
4103 
4104  // xinef: do not insert our application to interruptible list if application target is not the owner (area auras)
4105  // xinef: event if it gets removed, it will be reapplied in a second
4106  if (aura->GetSpellInfo()->AuraInterruptFlags && this == aura->GetOwner())
4107  {
4108  m_interruptableAuras.remove(aurApp);
4110  }
4111 
4112  bool auraStateFound = false;
4113  AuraStateType auraState = aura->GetSpellInfo()->GetAuraState();
4114  if (auraState)
4115  {
4116  bool canBreak = false;
4117  // Get mask of all aurastates from remaining auras
4118  for (AuraStateAurasMap::iterator itr = m_auraStateAuras.lower_bound(auraState); itr != m_auraStateAuras.upper_bound(auraState) && !(auraStateFound && canBreak);)
4119  {
4120  if (itr->second == aurApp)
4121  {
4122  m_auraStateAuras.erase(itr);
4123  itr = m_auraStateAuras.lower_bound(auraState);
4124  canBreak = true;
4125  continue;
4126  }
4127  auraStateFound = true;
4128  ++itr;
4129  }
4130  }
4131 
4132  aurApp->_Remove();
4133  aura->_UnapplyForTarget(this, caster, aurApp);
4134 
4135  // remove effects of the spell - needs to be done after removing aura from lists
4136  for (uint8 itr = 0; itr < MAX_SPELL_EFFECTS; ++itr)
4137  {
4138  if (aurApp->HasEffect(itr))
4139  aurApp->_HandleEffect(itr, false);
4140  }
4141 
4142  // all effect mustn't be applied
4143  ASSERT(!aurApp->GetEffectMask());
4144 
4145  // Remove totem at next update if totem loses its aura
4146  if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && IsTotem() && GetGUID() == aura->GetCasterGUID())
4147  {
4148  if (ToTotem()->GetSpell() == aura->GetId() && ToTotem()->GetTotemType() == TOTEM_PASSIVE)
4150  }
4151 
4152  // Remove aurastates only if were not found
4153  if (!auraStateFound)
4154  ModifyAuraState(auraState, false);
4155 
4156  aura->HandleAuraSpecificMods(aurApp, caster, false, false);
4157 
4158  // only way correctly remove all auras from list
4159  //if (removedAuras != m_removedAurasCount) new aura may be added
4160  i = m_appliedAuras.begin();
4161 }
4162 
4164 {
4165  // aura can be removed from unit only if it's applied on it, shouldn't happen
4166  ASSERT(aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) == aurApp);
4167 
4168  uint32 spellId = aurApp->GetBase()->GetId();
4169  AuraApplicationMapBoundsNonConst range = m_appliedAuras.equal_range(spellId);
4170 
4171  for (AuraApplicationMap::iterator iter = range.first; iter != range.second;)
4172  {
4173  if (iter->second == aurApp)
4174  {
4175  _UnapplyAura(iter, removeMode);
4176  return;
4177  }
4178  else
4179  ++iter;
4180  }
4181  ABORT();
4182 }
4183 
4185 {
4186  //SpellInfo const* spellProto = aura->GetSpellInfo();
4187 
4188  // passive spell special case (only non stackable with ranks)
4189 
4190  // xinef: this check makes caster to have 2 area auras thanks to spec switch
4191  // if (spellProto->IsPassiveStackableWithRanks())
4192  // return;
4193 
4194  bool remove = false;
4195  for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i)
4196  {
4197  if (remove)
4198  {
4199  remove = false;
4200  i = m_appliedAuras.begin();
4201  }
4202 
4203  if (aura->CanStackWith(i->second->GetBase(), true))
4204  continue;
4205 
4207  if (i == m_appliedAuras.end())
4208  break;
4209  remove = true;
4210  }
4211 }
4212 
4214 {
4215  if (apply)
4216  m_modAuras[aurEff->GetAuraType()].push_back(aurEff);
4217  else
4218  m_modAuras[aurEff->GetAuraType()].remove(aurEff);
4219 }
4220 
4221 // All aura base removes should go threw this function!
4222 void Unit::RemoveOwnedAura(AuraMap::iterator& i, AuraRemoveMode removeMode)
4223 {
4224  Aura* aura = i->second;
4225  ASSERT(!aura->IsRemoved());
4226 
4227  // if unit currently update aura list then make safe update iterator shift to next
4230 
4231  m_ownedAuras.erase(i);
4232  m_removedAuras.push_back(aura);
4233 
4234  // Unregister single target aura
4235  if (aura->IsSingleTarget())
4236  aura->UnregisterSingleTarget();
4237 
4238  aura->_Remove(removeMode);
4239 
4240  i = m_ownedAuras.begin();
4241 }
4242 
4243 void Unit::RemoveOwnedAura(uint32 spellId, ObjectGuid casterGUID, uint8 reqEffMask, AuraRemoveMode removeMode)
4244 {
4245  for (AuraMap::iterator itr = m_ownedAuras.lower_bound(spellId); itr != m_ownedAuras.upper_bound(spellId);)
4246  if (((itr->second->GetEffectMask() & reqEffMask) == reqEffMask) && (!casterGUID || itr->second->GetCasterGUID() == casterGUID))
4247  {
4248  RemoveOwnedAura(itr, removeMode);
4249  itr = m_ownedAuras.lower_bound(spellId);
4250  }
4251  else
4252  ++itr;
4253 }
4254 
4256 {
4257  if (aura->IsRemoved())
4258  return;
4259 
4260  ASSERT(aura->GetOwner() == this);
4261 
4262  uint32 spellId = aura->GetId();
4263  AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
4264 
4265  for (AuraMap::iterator itr = range.first; itr != range.second; ++itr)
4266  {
4267  if (itr->second == aura)
4268  {
4269  RemoveOwnedAura(itr, removeMode);
4270  return;
4271  }
4272  }
4273 
4274  ABORT();
4275 }
4276 
4277 Aura* Unit::GetOwnedAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, Aura* except) const
4278 {
4279  AuraMapBounds range = m_ownedAuras.equal_range(spellId);
4280  for (AuraMap::const_iterator itr = range.first; itr != range.second; ++itr)
4281  {
4282  if (((itr->second->GetEffectMask() & reqEffMask) == reqEffMask)
4283  && (!casterGUID || itr->second->GetCasterGUID() == casterGUID)
4284  && (!itemCasterGUID || itr->second->GetCastItemGUID() == itemCasterGUID)
4285  && (!except || except != itr->second))
4286  {
4287  return itr->second;
4288  }
4289  }
4290  return nullptr;
4291 }
4292 
4293 void Unit::RemoveAura(AuraApplicationMap::iterator& i, AuraRemoveMode mode)
4294 {
4295  AuraApplication* aurApp = i->second;
4296  // Do not remove aura which is already being removed
4297  if (aurApp->GetRemoveMode())
4298  return;
4299  Aura* aura = aurApp->GetBase();
4300  _UnapplyAura(i, mode);
4301  // Remove aura - for Area and Target auras
4302  if (aura->GetOwner() == this)
4303  aura->Remove(mode);
4304 
4305  sScriptMgr->OnAuraRemove(this, aurApp, mode);
4306 }
4307 
4308 void Unit::RemoveAura(uint32 spellId, ObjectGuid caster, uint8 reqEffMask, AuraRemoveMode removeMode)
4309 {
4310  AuraApplicationMapBoundsNonConst range = m_appliedAuras.equal_range(spellId);
4311  for (AuraApplicationMap::iterator iter = range.first; iter != range.second;)
4312  {
4313  Aura const* aura = iter->second->GetBase();
4314  if (((aura->GetEffectMask() & reqEffMask) == reqEffMask)
4315  && (!caster || aura->GetCasterGUID() == caster))
4316  {
4317  RemoveAura(iter, removeMode);
4318  return;
4319  }
4320  else
4321  ++iter;
4322  }
4323 }
4324 
4326 {
4327  // we've special situation here, RemoveAura called while during aura removal
4328  // this kind of call is needed only when aura effect removal handler
4329  // or event triggered by it expects to remove
4330  // not yet removed effects of an aura
4331  if (aurApp->GetRemoveMode())
4332  {
4333  // remove remaining effects of an aura
4334  for (uint8 itr = 0; itr < MAX_SPELL_EFFECTS; ++itr)
4335  {
4336  if (aurApp->HasEffect(itr))
4337  aurApp->_HandleEffect(itr, false);
4338  }
4339  return;
4340  }
4341  // no need to remove
4342  if (aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) != aurApp || aurApp->GetBase()->IsRemoved())
4343  return;
4344 
4345  uint32 spellId = aurApp->GetBase()->GetId();
4346  AuraApplicationMapBoundsNonConst range = m_appliedAuras.equal_range(spellId);
4347 
4348  for (AuraApplicationMap::iterator iter = range.first; iter != range.second;)
4349  {
4350  if (aurApp == iter->second)
4351  {
4352  RemoveAura(iter, mode);
4353  return;
4354  }
4355  else
4356  ++iter;
4357  }
4358 }
4359 
4361 {
4362  if (aura->IsRemoved())
4363  return;
4364  if (AuraApplication* aurApp = aura->GetApplicationOfTarget(GetGUID()))
4365  RemoveAura(aurApp, mode);
4366 }
4367 
4368 void Unit::RemoveOwnedAuras(std::function<bool(Aura const*)> const& check)
4369 {
4370  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4371  {
4372  if (check(iter->second))
4373  {
4374  RemoveOwnedAura(iter);
4375  continue;
4376  }
4377  ++iter;
4378  }
4379 }
4380 
4381 void Unit::RemoveAppliedAuras(std::function<bool(AuraApplication const*)> const& check)
4382 {
4383  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4384  {
4385  if (check(iter->second))
4386  {
4387  RemoveAura(iter);
4388  continue;
4389  }
4390  ++iter;
4391  }
4392 }
4393 
4394 void Unit::RemoveOwnedAuras(uint32 spellId, std::function<bool(Aura const*)> const& check)
4395 {
4396  for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);)
4397  {
4398  if (check(iter->second))
4399  {
4400  RemoveOwnedAura(iter);
4401  continue;
4402  }
4403  ++iter;
4404  }
4405 }
4406 
4407 void Unit::RemoveAppliedAuras(uint32 spellId, std::function<bool(AuraApplication const*)> const& check)
4408 {
4409  for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
4410  {
4411  if (check(iter->second))
4412  {
4413  RemoveAura(iter);
4414  continue;
4415  }
4416  ++iter;
4417  }
4418 }
4419 
4420 void Unit::RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID, uint8 reqEffMask, AuraRemoveMode removeMode)
4421 {
4422  for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
4423  {
4424  Aura const* aura = iter->second->GetBase();
4425  if (((aura->GetEffectMask() & reqEffMask) == reqEffMask)
4426  && (!casterGUID || aura->GetCasterGUID() == casterGUID))
4427  {
4428  RemoveAura(iter, removeMode);
4429  iter = m_appliedAuras.lower_bound(spellId);
4430  }
4431  else
4432  ++iter;
4433  }
4434 }
4435 
4436 void Unit::RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID, AuraRemoveMode removeMode)
4437 {
4438  AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
4439  for (AuraMap::iterator iter = range.first; iter != range.second;)
4440  {
4441  Aura* aura = iter->second;
4442  if ((aura->GetType() == UNIT_AURA_TYPE)
4443  && (!casterGUID || aura->GetCasterGUID() == casterGUID))
4444  {
4445  aura->ModStackAmount(-1, removeMode);
4446  return;
4447  }
4448  else
4449  ++iter;
4450  }
4451 }
4452 
4453 void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, ObjectGuid casterGUID, Unit* dispeller, uint8 chargesRemoved/*= 1*/)
4454 {
4455  AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
4456  for (AuraMap::iterator iter = range.first; iter != range.second;)
4457  {
4458  Aura* aura = iter->second;
4459  if (aura->GetCasterGUID() == casterGUID)
4460  {
4461  DispelInfo dispelInfo(dispeller, dispellerSpellId, chargesRemoved);
4462 
4463  // Call OnDispel hook on AuraScript
4464  aura->CallScriptDispel(&dispelInfo);
4465 
4468  else
4470 
4471  // Call AfterDispel hook on AuraScript
4472  aura->CallScriptAfterDispel(&dispelInfo);
4473 
4474  switch (aura->GetSpellInfo()->SpellFamilyName)
4475  {
4476  case SPELLFAMILY_HUNTER:
4477  {
4478  // Noxious Stings
4479  if (aura->GetSpellInfo()->SpellFamilyFlags[1] & 0x1000)
4480  {
4481  if (Unit* caster = aura->GetCaster())
4482  {
4483  if (AuraEffect* aureff = caster->GetAuraEffect(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS, SPELLFAMILY_HUNTER, 3521, 1))
4484  {
4485  if (Aura* noxious = Aura::TryCreate(aura->GetSpellInfo(), aura->GetEffectMask(), dispeller, caster))
4486  {
4487  noxious->SetDuration(aura->GetDuration() * aureff->GetAmount() / 100);
4488  if (aura->GetUnitOwner() )
4489  if (const std::vector<int32>* spell_triggered = sSpellMgr->GetSpellLinked(-int32(aura->GetId())))
4490  for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
4491  aura->GetUnitOwner()->RemoveAurasDueToSpell(*itr);
4492  }
4493  }
4494  }
4495  }
4496  break;
4497  }
4499  {
4500  // Icy Clutch, remove with Frost Fever
4501  if (aura->GetSpellInfo()->SpellFamilyFlags[1] & 0x4000000)
4502  {
4503  if (AuraEffect* aureff = GetAuraEffect(SPELL_AURA_MOD_DECREASE_SPEED, SPELLFAMILY_DEATHKNIGHT, 0, 0x40000, 0, casterGUID))
4504  RemoveAurasDueToSpell(aureff->GetId());
4505  }
4506  }
4507  default:
4508  break;
4509  }
4510  return;
4511  }
4512  else
4513  ++iter;
4514  }
4515 }
4516 
4517 void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, Unit* stealer)
4518 {
4519  AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
4520  for (AuraMap::iterator iter = range.first; iter != range.second;)
4521  {
4522  Aura* aura = iter->second;
4523  if (aura->GetCasterGUID() == casterGUID)
4524  {
4525  int32 damage[MAX_SPELL_EFFECTS];
4526  int32 baseDamage[MAX_SPELL_EFFECTS];
4527  uint8 effMask = 0;
4528  uint8 recalculateMask = 0;
4529  Unit* caster = aura->GetCaster();
4530  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
4531  {
4532  if (aura->GetEffect(i))
4533  {
4534  baseDamage[i] = aura->GetEffect(i)->GetBaseAmount();
4535  damage[i] = aura->GetEffect(i)->GetAmount();
4536  effMask |= (1 << i);
4537  if (aura->GetEffect(i)->CanBeRecalculated())
4538  recalculateMask |= (1 << i);
4539  }
4540  else
4541  {
4542  baseDamage[i] = 0;
4543  damage[i] = 0;
4544  }
4545  }
4546 
4547  bool stealCharge = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_REMOVES_CHARGES);
4548  // Cast duration to unsigned to prevent permanent aura's such as Righteous Fury being permanently added to caster
4549  uint32 dur = std::min(2u * MINUTE * IN_MILLISECONDS, uint32(aura->GetDuration()));
4550 
4551  if (Aura* oldAura = stealer->GetAura(aura->GetId(), aura->GetCasterGUID()))
4552  {
4553  if (stealCharge)
4554  oldAura->ModCharges(1);
4555  else
4556  oldAura->ModStackAmount(1);
4557  oldAura->SetDuration(int32(dur));
4558  }
4559  else
4560  {
4561  // single target state must be removed before aura creation to preserve existing single target aura
4562  if (aura->IsSingleTarget())
4563  aura->UnregisterSingleTarget();
4564 
4565  // Xinef: if stealer has same aura
4566  Aura* curAura = stealer->GetAura(aura->GetId());
4567  if (!curAura || (!curAura->IsPermanent() && curAura->GetDuration() < (int32)dur))
4568  if (Aura* newAura = Aura::TryRefreshStackOrCreate(aura->GetSpellInfo(), effMask, stealer, nullptr, &baseDamage[0], nullptr, aura->GetCasterGUID()))
4569  {
4570  // created aura must not be single target aura,, so stealer won't loose it on recast
4571  if (newAura->IsSingleTarget())
4572  {
4573  newAura->UnregisterSingleTarget();
4574  // bring back single target aura status to the old aura
4575  aura->SetIsSingleTarget(true);
4576  caster->GetSingleCastAuras().push_back(aura);
4577  }
4578  // FIXME: using aura->GetMaxDuration() maybe not blizzlike but it fixes stealing of spells like Innervate
4579  newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? 1 : aura->GetCharges(), 1, recalculateMask, &damage[0]);
4580  newAura->ApplyForTargets();
4581  }
4582  }
4583 
4584  if (stealCharge)
4586  else
4588 
4589  return;
4590  }
4591  else
4592  ++iter;
4593  }
4594 }
4595 
4597 {
4598  for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
4599  {
4600  if (iter->second->GetBase()->GetCastItemGUID() == castItemGuid)
4601  {
4602  RemoveAura(iter);
4603  iter = m_appliedAuras.lower_bound(spellId);
4604  }
4605  else
4606  ++iter;
4607  }
4608 }
4609 
4610 void Unit::RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID, Aura* except, bool negative, bool positive)
4611 {
4612  // simple check if list is empty
4613  if (m_modAuras[auraType].empty())
4614  return;
4615 
4616  for (AuraEffectList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();)
4617  {
4618  Aura* aura = (*iter)->GetBase();
4619  AuraApplication* aurApp = aura->GetApplicationOfTarget(GetGUID());
4620 
4621  ++iter;
4622  if (aura != except && (!casterGUID || aura->GetCasterGUID() == casterGUID)
4623  && ((negative && !aurApp->IsPositive()) || (positive && aurApp->IsPositive())))
4624  {
4625  uint32 removedAuras = m_removedAurasCount;
4626  RemoveAura(aurApp);
4627  if (m_removedAurasCount > removedAuras + 1)
4628  iter = m_modAuras[auraType].begin();
4629  }
4630  }
4631 }
4632 
4634 {
4635  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4636  {
4637  SpellInfo const* spell = iter->second->GetBase()->GetSpellInfo();
4638  if (spell->Attributes & flags)
4639  RemoveAura(iter);
4640  else
4641  ++iter;
4642  }
4643 }
4644 
4646 {
4647  // single target auras from other casters
4648  // Iterate m_ownedAuras - aura is marked as single target in Unit::AddAura (and pushed to m_ownedAuras).
4649  // m_appliedAuras will NOT contain the aura before first Unit::Update after adding it to m_ownedAuras.
4650  // Quickly removing such an aura will lead to it not being unregistered from caster's single cast auras container
4651  // leading to assertion failures if the aura was cast on a player that can
4652  // (and is changing map at the point where this function is called).
4653  // Such situation occurs when player is logging in inside an instance and fails the entry check for any reason.
4654  // The aura that was loaded from db (indirectly, via linked casts) gets removed before it has a chance
4655  // to register in m_appliedAuras
4656  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4657  {
4658  Aura const* aura = iter->second;
4659 
4660  if (aura->GetCasterGUID() != GetGUID() && aura->IsSingleTarget())
4661  RemoveOwnedAura(iter);
4662  else
4663  ++iter;
4664  }
4665 
4666  // single target auras at other targets
4667  AuraList& scAuras = GetSingleCastAuras();
4668  for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
4669  {
4670  Aura* aura = *iter;
4671  if (aura->GetUnitOwner() != this)
4672  {
4673  aura->Remove();
4674  iter = scAuras.begin();
4675  }
4676  else
4677  ++iter;
4678  }
4679 }
4680 
4682 {
4683  if (!(m_interruptMask & flag))
4684  return;
4685 
4686  // interrupt auras
4687  for (AuraApplicationList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end();)
4688  {
4689  Aura* aura = (*iter)->GetBase();
4690  ++iter;
4691  if ((aura->GetSpellInfo()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except))
4692  {
4693  uint32 removedAuras = m_removedAurasCount;
4694  RemoveAura(aura);
4695  if (m_removedAurasCount > removedAuras + 1)
4696  iter = m_interruptableAuras.begin();
4697  }
4698  }
4699 
4700  // interrupt channeled spell
4702  if (spell->getState() == SPELL_STATE_CASTING
4703  && (spell->m_spellInfo->ChannelInterruptFlags & flag)
4704  && spell->m_spellInfo->Id != except)
4705  InterruptNonMeleeSpells(false, spell->m_spellInfo->Id);
4706 
4708 }
4709 
4710 void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID)
4711 {
4712  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4713  {
4714  Aura const* aura = iter->second->GetBase();
4715  if (!casterGUID || aura->GetCasterGUID() == casterGUID)
4716  {
4717  SpellInfo const* spell = aura->GetSpellInfo();
4718  if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3))
4719  {
4720  RemoveAura(iter);
4721  continue;
4722  }
4723  }
4724  ++iter;
4725  }
4726 }
4727 
4729 {
4730  if (withRoot)
4732 
4733  // Snares
4734  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4735  {
4736  Aura const* aura = iter->second->GetBase();
4737  if (aura->GetSpellInfo()->Mechanic == MECHANIC_SNARE)
4738  {
4739  RemoveAura(iter);
4740  continue;
4741  }
4742 
4743  // Xinef: turn off snare auras by setting amount to 0 :)
4744  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
4745  if (((1 << i) & iter->second->GetEffectMask()) && aura->GetSpellInfo()->Effects[i].Mechanic == MECHANIC_SNARE)
4746  aura->GetEffect(i)->ChangeAmount(0);
4747 
4748  ++iter;
4749  }
4750 }
4751 
4752 void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode, uint32 except)
4753 {
4754  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4755  {
4756  Aura const* aura = iter->second->GetBase();
4757  if (!except || aura->GetId() != except)
4758  {
4759  if (aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanic_mask)
4760  {
4761  RemoveAura(iter, removemode);
4762  continue;
4763  }
4764  }
4765  ++iter;
4766  }
4767 }
4768 
4770 {
4771  uint32 mechanic_mask = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT);
4772  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4773  {
4774  Aura const* aura = iter->second->GetBase();
4775  if ((aura->GetSpellInfo()->GetAllEffectsMechanicMask() & mechanic_mask) &&
4777  {
4778  RemoveAura(iter);
4779  continue;
4780  }
4781  ++iter;
4782  }
4783 }
4784 
4786 {
4787  // make sure that all area auras not applied on self are removed - prevent access to deleted pointer later
4788  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4789  {
4790  Aura* aura = iter->second;
4791  ++iter;
4792  Aura::ApplicationMap const& appMap = aura->GetApplicationMap();
4793  for (Aura::ApplicationMap::const_iterator itr = appMap.begin(); itr != appMap.end();)
4794  {
4795  AuraApplication* aurApp = itr->second;
4796  ++itr;
4797  Unit* target = aurApp->GetTarget();
4798  if (target == this)
4799  continue;
4800  target->RemoveAura(aurApp);
4801  // things linked on aura remove may apply new area aura - so start from the beginning
4802  iter = m_ownedAuras.begin();
4803  }
4804  }
4805 
4806  // remove area auras owned by others
4807  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4808  {
4809  if (iter->second->GetBase()->GetOwner() != this)
4810  {
4811  RemoveAura(iter);
4812  }
4813  else
4814  ++iter;
4815  }
4816 }
4817 
4819 {
4820  // this may be a dead loop if some events on aura remove will continiously apply aura on remove
4821  // we want to have all auras removed, so use your brain when linking events
4822  while (!m_appliedAuras.empty() || !m_ownedAuras.empty())
4823  {
4824  AuraApplicationMap::iterator aurAppIter;
4825  for (aurAppIter = m_appliedAuras.begin(); aurAppIter != m_appliedAuras.end();)
4826  _UnapplyAura(aurAppIter, AURA_REMOVE_BY_DEFAULT);
4827 
4828  AuraMap::iterator aurIter;
4829  for (aurIter = m_ownedAuras.begin(); aurIter != m_ownedAuras.end();)
4830  RemoveOwnedAura(aurIter);
4831  }
4832 }
4833 
4835 {
4836  // in join, remove positive buffs, on end, remove negative
4837  // used to remove positive visible auras in arenas
4838  RemoveAppliedAuras([](AuraApplication const* aurApp)
4839  {
4840  Aura const* aura = aurApp->GetBase();
4841  return (!aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_ALLOW_ENETRING_ARENA) // don't remove stances, shadowform, pally/hunter auras
4842  && !aura->IsPassive() // don't remove passive auras
4843  && (aurApp->IsPositive() || !aura->GetSpellInfo()->HasAttribute(SPELL_ATTR3_ALLOW_AURA_WHILE_DEAD))) || // not negative death persistent auras
4844  aura->GetSpellInfo()->HasAttribute(SPELL_ATTR5_REMOVE_ENTERING_ARENA); // special marker, always remove
4845  });
4846 }
4847 
4849 {
4850  // used just after dieing to remove all visible auras
4851  // and disable the mods for the passive ones
4852  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4853  {
4854  Aura const* aura = iter->second->GetBase();
4857  else
4858  ++iter;
4859  }
4860 
4861  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4862  {
4863  Aura* aura = iter->second;
4866  else
4867  ++iter;
4868  }
4869 }
4870 
4872 {
4873  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4874  {
4875  Aura const* aura = iter->second->GetBase();
4876  if (!aura->IsPassive() && aura->GetSpellInfo()->IsRequiringDeadTarget())
4878  else
4879  ++iter;
4880  }
4881 
4882  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4883  {
4884  Aura* aura = iter->second;
4885  if (!aura->IsPassive() && aura->GetSpellInfo()->IsRequiringDeadTarget())
4887  else
4888  ++iter;
4889  }
4890 }
4891 
4893 {
4894  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4895  {
4896  Aura const* aura = iter->second->GetBase();
4897  if (aura->GetSpellInfo()->HasAura(type))
4898  ++iter;
4899  else
4901  }
4902 
4903  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4904  {
4905  Aura* aura = iter->second;
4906  if (aura->GetSpellInfo()->HasAura(type))
4907  ++iter;
4908  else
4910  }
4911 }
4912 
4913 // pussywizard: replaced with Unit::RemoveEvadeAuras()
4914 /*void Unit::RemoveAllAurasExceptType(AuraType type1, AuraType type2)
4915 {
4916  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4917  {
4918  Aura const* aura = iter->second->GetBase();
4919  if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2))
4920  ++iter;
4921  else
4922  _UnapplyAura(iter, AURA_REMOVE_BY_DEFAULT);
4923  }
4924 
4925  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4926  {
4927  Aura* aura = iter->second;
4928  if (aura->GetSpellInfo()->HasAura(type1) || aura->GetSpellInfo()->HasAura(type2))
4929  ++iter;
4930  else
4931  RemoveOwnedAura(iter, AURA_REMOVE_BY_DEFAULT);
4932  }
4933 }*/
4934 
4935 // Xinef: We should not remove passive auras on evade, if npc has player owner (scripted one cast auras)
4937 {
4938  for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();)
4939  {
4940  Aura const* aura = iter->second->GetBase();
4942  ++iter;
4943  else
4945  }
4946 
4947  for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();)
4948  {
4949  Aura* aura = iter->second;
4951  ++iter;
4952  else
4954  }
4955 }
4956 
4957 void Unit::DelayOwnedAuras(uint32 spellId, ObjectGuid caster, int32 delaytime)
4958 {
4959  AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
4960  for (; range.first != range.second; ++range.first)
4961  {
4962  Aura* aura = range.first->second;
4963  if (!caster || aura->GetCasterGUID() == caster)
4964  {
4965  if (aura->GetDuration() < delaytime)
4966  aura->SetDuration(0);
4967  else
4968  aura->SetDuration(aura->GetDuration() - delaytime);
4969 
4970  // update for out of range group members (on 1 slot use)
4972  LOG_DEBUG("spells.aura", "Aura %u partially interrupted on unit %s, new duration: %u ms", aura->GetId(), GetGUID().ToString().c_str(), aura->GetDuration());
4973  }
4974  }
4975 }
4976 
4978 {
4979  for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i)
4980  (*i).second->GetBase()->HandleAllEffects(i->second, AURA_EFFECT_HANDLE_STAT, false);
4981 }
4982 
4984 {
4985  for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i)
4986  (*i).second->GetBase()->HandleAllEffects(i->second, AURA_EFFECT_HANDLE_STAT, true);
4987 }
4988 
4989 AuraEffect* Unit::GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster) const
4990 {
4991  AuraApplicationMapBounds range = m_appliedAuras.equal_range(spellId);
4992  for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr)
4993  {
4994  if (itr->second->HasEffect(effIndex)
4995  && (!caster || itr->second->GetBase()->GetCasterGUID() == caster))
4996  {
4997  return itr->second->GetBase()->GetEffect(effIndex);
4998  }
4999  }
5000  return nullptr;
5001 }
5002 
5004 {
5005  uint32 rankSpell = sSpellMgr->GetFirstSpellInChain(spellId);
5006  while (rankSpell)
5007  {
5008  if (AuraEffect* aurEff = GetAuraEffect(rankSpell, effIndex, caster))
5009  return aurEff;
5010  rankSpell = sSpellMgr->GetNextSpellInChain(rankSpell);
5011  }
5012  return nullptr;
5013 }
5014 
5016 {
5017  AuraEffectList const& auras = GetAuraEffectsByType(type);
5018  for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
5019  {
5020  if (effIndex != (*itr)->GetEffIndex())
5021  continue;
5022  SpellInfo const* spell = (*itr)->GetSpellInfo();
5023  if (spell->SpellIconID == iconId && spell->SpellFamilyName == name)
5024  return *itr;
5025  }
5026  return nullptr;
5027 }
5028 
5029 AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID) const
5030 {
5031  AuraEffectList const& auras = GetAuraEffectsByType(type);
5032  for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
5033  {
5034  SpellInfo const* spell = (*i)->GetSpellInfo();
5035  if (spell->SpellFamilyName == uint32(family) && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3))
5036  {
5037  if (casterGUID && (*i)->GetCasterGUID() != casterGUID)
5038  continue;
5039  return (*i);
5040  }
5041  }
5042  return nullptr;
5043 }
5044 
5046 {
5048  for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
5049  {
5050  if ((*itr)->GetId() == spellid)
5051  return *itr;
5052  }
5053 
5054  return nullptr;
5055 }
5056 
5057 AuraApplication* Unit::GetAuraApplication(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, AuraApplication* except) const
5058 {
5059  AuraApplicationMapBounds range = m_appliedAuras.equal_range(spellId);
5060  for (; range.first != range.second; ++range.first)
5061  {
5062  AuraApplication* app = range.first->second;
5063  Aura const* aura = app->GetBase();
5064 
5065  if (((aura->GetEffectMask() & reqEffMask) == reqEffMask)
5066  && (!casterGUID || aura->GetCasterGUID() == casterGUID)
5067  && (!itemCasterGUID || aura->GetCastItemGUID() == itemCasterGUID)
5068  && (!except || except != app))
5069  {
5070  return app;
5071  }
5072  }
5073  return nullptr;
5074 }
5075 
5076 Aura* Unit::GetAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const
5077 {
5078  AuraApplication* aurApp = GetAuraApplication(spellId, casterGUID, itemCasterGUID, reqEffMask);
5079  return aurApp ? aurApp->GetBase() : nullptr;
5080 }
5081 
5082 AuraApplication* Unit::GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask, AuraApplication* except) const
5083 {
5084  uint32 rankSpell = sSpellMgr->GetFirstSpellInChain(spellId);
5085  while (rankSpell)
5086  {
5087  if (AuraApplication* aurApp = GetAuraApplication(rankSpell, casterGUID, itemCasterGUID, reqEffMask, except))
5088  return aurApp;
5089  rankSpell = sSpellMgr->GetNextSpellInChain(rankSpell);
5090  }
5091  return nullptr;
5092 }
5093 
5094 Aura* Unit::GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const
5095 {
5096  AuraApplication* aurApp = GetAuraApplicationOfRankedSpell(spellId, casterGUID, itemCasterGUID, reqEffMask);
5097  return aurApp ? aurApp->GetBase() : nullptr;
5098 }
5099 
5100 void Unit::GetDispellableAuraList(Unit* caster, uint32 dispelMask, DispelChargesList& dispelList)
5101 {
5102  // we should not be able to dispel diseases if the target is affected by unholy blight
5103  if (dispelMask & (1 << DISPEL_DISEASE) && HasAura(50536))
5104  dispelMask &= ~(1 << DISPEL_DISEASE);
5105 
5106  ReputationRank rank = GetReactionTo(caster);
5107  bool positive = rank >= REP_FRIENDLY;
5108 
5109  // Neutral unit not at war with caster should be treated as a friendly unit
5110  if (rank == REP_NEUTRAL)
5111  {
5112  if (Player* casterPlayer = caster->GetAffectingPlayer())
5113  {
5114  if (FactionTemplateEntry const* factionTemplateEntry = GetFactionTemplateEntry())
5115  {
5116  if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction))
5117  {
5118  if (factionEntry->CanBeSetAtWar())
5119  {
5120  positive = !casterPlayer->GetReputationMgr().IsAtWar(factionEntry);
5121  }
5122  }
5123  }
5124  }
5125  }
5126 
5127  Unit::VisibleAuraMap const* visibleAuras = GetVisibleAuras();
5128  for (Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr)
5129  {
5130  Aura* aura = itr->second->GetBase();
5131 
5132  // don't try to remove passive auras
5133  if (aura->IsPassive())
5134  continue;
5135 
5136  if (aura->GetSpellInfo()->GetDispelMask() & dispelMask)
5137  {
5138  if (aura->GetSpellInfo()->Dispel == DISPEL_MAGIC)
5139  {
5140  // do not remove positive auras if friendly target
5141  // negative auras if non-friendly target
5142  if (itr->second->IsPositive() == positive)
5143  continue;
5144  }
5145 
5146  // The charges / stack amounts don't count towards the total number of auras that can be dispelled.
5147  // Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
5148  // Polymorph instead of 1 / (5 + 1) -> 16%.
5149  bool dispel_charges = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_REMOVES_CHARGES);
5150  uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
5151  if (charges > 0)
5152  dispelList.push_back(std::make_pair(aura, charges));
5153  }
5154  }
5155 }
5156 
5157 bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster) const
5158 {
5159  AuraApplicationMapBounds range = m_appliedAuras.equal_range(spellId);
5160  for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr)
5161  {
5162  if (itr->second->HasEffect(effIndex)
5163  && (!caster || itr->second->GetBase()->GetCasterGUID() == caster))
5164  {
5165  return true;
5166  }
5167  }
5168  return false;
5169 }
5170 
5172 {
5173  uint32 count = 0;
5174  AuraApplicationMapBounds range = m_appliedAuras.equal_range(spellId);
5175 
5176  for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr)
5177  {
5178  if (itr->second->GetBase()->GetStackAmount() == 0)
5179  ++count;
5180  else
5181  count += (uint32)itr->second->GetBase()->GetStackAmount();
5182  }
5183 
5184  return count;
5185 }
5186 
5187 bool Unit::HasAura(uint32 spellId, ObjectGuid casterGUID, ObjectGuid itemCasterGUID, uint8 reqEffMask) const
5188 {
5189  if (GetAuraApplication(spellId, casterGUID, itemCasterGUID, reqEffMask))
5190  return true;
5191  return false;
5192 }
5193 
5194 bool Unit::HasAuraType(AuraType auraType) const
5195 {
5196  return (!m_modAuras[auraType].empty());
5197 }
5198 
5200 {
5201  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5202  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5203  if (caster == (*i)->GetCasterGUID())
5204  return true;
5205  return false;
5206 }
5207 
5209 {
5210  AuraEffectList const& mAuraList = GetAuraEffectsByType(auraType);
5211  for (AuraEffectList::const_iterator i = mAuraList.begin(); i != mAuraList.end(); ++i)
5212  if( (*i)->GetBase()->CanBeSentToClient() )
5213  return true;
5214 
5215  return false;
5216 }
5217 
5218 bool Unit::HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const
5219 {
5220  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5221  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5222  if (miscvalue == (*i)->GetMiscValue())
5223  return true;
5224  return false;
5225 }
5226 
5227 bool Unit::HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const
5228 {
5229  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5230  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5231  if ((*i)->IsAffectedOnSpell(affectedSpell))
5232  return true;
5233  return false;
5234 }
5235 
5237 {
5238  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5239  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5240  if (value == (*i)->GetAmount())
5241  return true;
5242  return false;
5243 }
5244 
5246 {
5247  if (!(m_interruptMask & flag))
5248  return false;
5249  for (AuraApplicationList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); ++iter)
5250  {
5251  if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellInfo()->AuraInterruptFlags & flag && (!guid || (*iter)->GetBase()->GetCasterGUID() == guid))
5252  return true;
5253  }
5254  return false;
5255 }
5256 
5258 {
5259  for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter)
5260  {
5261  Aura const* aura = iter->second->GetBase();
5262  if (!iter->second->IsPositive() && aura->GetSpellInfo()->Attributes & flag && (!guid || aura->GetCasterGUID() == guid))
5263  return true;
5264  }
5265  return false;
5266 }
5267 
5268 bool Unit::HasAuraWithMechanic(uint32 mechanicMask) const
5269 {
5270  for (AuraApplicationMap::const_iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end(); ++iter)
5271  {
5272  SpellInfo const* spellInfo = iter->second->GetBase()->GetSpellInfo();
5273  if (spellInfo->Mechanic && (mechanicMask & (1 << spellInfo->Mechanic)))
5274  return true;
5275 
5276  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
5277  if (iter->second->HasEffect(i) && spellInfo->Effects[i].Effect && spellInfo->Effects[i].Mechanic)
5278  if (mechanicMask & (1 << spellInfo->Effects[i].Mechanic))
5279  return true;
5280  }
5281 
5282  return false;
5283 }
5284 
5286 {
5288  for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
5289  {
5290  if ((*i)->GetMiscValue() == script)
5291  if ((*i)->IsAffectedOnSpell(spell))
5292  return (*i);
5293  }
5294  return nullptr;
5295 }
5296 
5298 {
5299  static const AuraType diseaseAuraTypes[] =
5300  {
5301  SPELL_AURA_PERIODIC_DAMAGE, // Frost Fever and Blood Plague
5302  SPELL_AURA_LINKED, // Crypt Fever and Ebon Plague
5304  };
5305 
5306  ObjectGuid drwGUID;
5307 
5308  if (Player* playerCaster = ObjectAccessor::GetPlayer(*this, casterGUID))
5309  drwGUID = playerCaster->getRuneWeaponGUID();
5310 
5311  uint32 diseases = 0;
5312  for (uint8 index = 0; diseaseAuraTypes[index] != SPELL_AURA_NONE; ++index)
5313  {
5314  for (AuraEffectList::iterator i = m_modAuras[diseaseAuraTypes[index]].begin(); i != m_modAuras[diseaseAuraTypes[index]].end();)
5315  {
5316  // Get auras with disease dispel type by caster
5317  if ((*i)->GetSpellInfo()->Dispel == DISPEL_DISEASE
5318  && ((*i)->GetCasterGUID() == casterGUID || (*i)->GetCasterGUID() == drwGUID)) // if its caster or his dancing rune weapon
5319  {
5320  ++diseases;
5321 
5322  if (mode == 1)
5323  {
5324  RemoveAura((*i)->GetId(), (*i)->GetCasterGUID());
5325  i = m_modAuras[diseaseAuraTypes[index]].begin();
5326  continue;
5327  }
5328  // used for glyph of scourge strike
5329  else if (mode == 2)
5330  {
5331  Aura* aura = (*i)->GetBase();
5332  if (aura && !aura->IsRemoved() && aura->GetDuration() > 0)
5333  if ((aura->GetApplyTime() + aura->GetMaxDuration() / 1000 + 8) > (time(nullptr) + aura->GetDuration() / 1000))
5334  aura->SetDuration(aura->GetDuration() + 3000);
5335  }
5336  }
5337  ++i;
5338  }
5339  }
5340  return diseases;
5341 }
5342 
5344 {
5345  static const AuraType diseaseAuraTypes[] =
5346  {
5350  };
5351 
5352  uint32 dots = 0;
5353  for (AuraType const* itr = &diseaseAuraTypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr)
5354  {
5355  Unit::AuraEffectList const& auras = GetAuraEffectsByType(*itr);
5356  for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
5357  {
5358  // Get auras by caster
5359  if ((*i)->GetCasterGUID() == casterGUID)
5360  ++dots;
5361  }
5362  }
5363  return dots;
5364 }
5365 
5367 {
5368  int32 modifier = 0;
5369  int32 areaModifier = 0;
5370 
5371  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5372  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5373  {
5374  if ((*i)->GetSpellInfo()->HasAreaAuraEffect())
5375  {
5376  if (areaModifier < (*i)->GetAmount())
5377  areaModifier = (*i)->GetAmount();
5378  }
5379  else
5380  modifier += (*i)->GetAmount();
5381  }
5382 
5383  return modifier + areaModifier;
5384 }
5385 
5387 {
5388  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5389  if (mTotalAuraList.empty())
5390  return 0;
5391 
5392  int32 modifier = 0;
5393 
5394  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5395  modifier += (*i)->GetAmount();
5396 
5397  return modifier;
5398 }
5399 
5401 {
5402  float multiplier = 1.0f;
5403 
5404  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5405  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5406  AddPct(multiplier, (*i)->GetAmount());
5407 
5408  return multiplier;
5409 }
5410 
5412 {
5413  int32 modifier = 0;
5414 
5415  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5416  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5417  {
5418  if ((*i)->GetAmount() > modifier)
5419  modifier = (*i)->GetAmount();
5420  }
5421 
5422  return modifier;
5423 }
5424 
5426 {
5427  int32 modifier = 0;
5428 
5429  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5430  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5431  if ((*i)->GetAmount() < modifier)
5432  modifier = (*i)->GetAmount();
5433 
5434  return modifier;
5435 }
5436 
5438 {
5439  int32 modifier = 0;
5440 
5441  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5442  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5443  {
5444  if ((*i)->GetMiscValue()& misc_mask)
5445  modifier += (*i)->GetAmount();
5446  }
5447  return modifier;
5448 }
5449 
5451 {
5452  float multiplier = 1.0f;
5453 
5454  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5455  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5456  if (((*i)->GetMiscValue() & misc_mask))
5457  AddPct(multiplier, (*i)->GetAmount());
5458 
5459  return multiplier;
5460 }
5461 
5463 {
5464  int32 modifier = 0;
5465 
5466  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5467  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5468  {
5469  if (except != (*i) && (*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() > modifier)
5470  modifier = (*i)->GetAmount();
5471  }
5472 
5473  return modifier;
5474 }
5475 
5477 {
5478  int32 modifier = 0;
5479 
5480  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5481  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5482  {
5483  if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() < modifier)
5484  modifier = (*i)->GetAmount();
5485  }
5486 
5487  return modifier;
5488 }
5489 
5491 {
5492  int32 modifier = 0;
5493 
5494  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5495  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5496  if ((*i)->GetMiscValue() == misc_value)
5497  modifier += (*i)->GetAmount();
5498 
5499  return modifier;
5500 }
5501 
5502 float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const
5503 {
5504  float multiplier = 1.0f;
5505 
5506  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5507  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5508  if ((*i)->GetMiscValue() == misc_value)
5509  AddPct(multiplier, (*i)->GetAmount());
5510 
5511  return multiplier;
5512 }
5513 
5515 {
5516  int32 modifier = 0;
5517 
5518  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5519  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5520  {
5521  if ((*i)->GetMiscValue() == misc_value && (*i)->GetAmount() > modifier)
5522  modifier = (*i)->GetAmount();
5523  }
5524 
5525  return modifier;
5526 }
5527 
5529 {
5530  int32 modifier = 0;
5531 
5532  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5533  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5534  {
5535  if ((*i)->GetMiscValue() == misc_value && (*i)->GetAmount() < modifier)
5536  modifier = (*i)->GetAmount();
5537  }
5538 
5539  return modifier;
5540 }
5541 
5543 {
5544  int32 modifier = 0;
5545 
5546  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5547  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5548  if ((*i)->IsAffectedOnSpell(affectedSpell))
5549  modifier += (*i)->GetAmount();
5550 
5551  return modifier;
5552 }
5553 
5554 float Unit::GetTotalAuraMultiplierByAffectMask(AuraType auratype, SpellInfo const* affectedSpell) const
5555 {
5556  float multiplier = 1.0f;
5557 
5558  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5559  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5560  if ((*i)->IsAffectedOnSpell(affectedSpell))
5561  AddPct(multiplier, (*i)->GetAmount());
5562 
5563  return multiplier;
5564 }
5565 
5567 {
5568  int32 modifier = 0;
5569 
5570  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5571  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5572  {
5573  if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() > modifier)
5574  modifier = (*i)->GetAmount();
5575  }
5576 
5577  return modifier;
5578 }
5579 
5581 {
5582  int32 modifier = 0;
5583 
5584  AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype);
5585  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
5586  {
5587  if ((*i)->IsAffectedOnSpell(affectedSpell) && (*i)->GetAmount() < modifier)
5588  modifier = (*i)->GetAmount();
5589  }
5590 
5591  return modifier;
5592 }
5593 
5595 {
5596  m_dynObj.push_back(dynObj);
5597 }
5598 
5600 {
5601  m_dynObj.remove(dynObj);
5602 }
5603 
5605 {
5606  if (m_dynObj.empty())
5607  return nullptr;
5608  for (DynObjectList::const_iterator i = m_dynObj.begin(); i != m_dynObj.end(); ++i)
5609  {
5610  DynamicObject* dynObj = *i;
5611  if (dynObj->GetSpellId() == spellId)
5612  return dynObj;
5613  }
5614  return nullptr;
5615 }
5616 
5618 {
5619  if (m_dynObj.empty())
5620  return;
5621  for (DynObjectList::iterator i = m_dynObj.begin(); i != m_dynObj.end();)
5622  {
5623  DynamicObject* dynObj = *i;
5624  if (dynObj->GetSpellId() == spellId)
5625  {
5626  dynObj->Remove();
5627  i = m_dynObj.begin();
5628  }
5629  else
5630  ++i;
5631  }
5632 }
5633 
5635 {
5636  while (!m_dynObj.empty())
5637  m_dynObj.front()->Remove();
5638 }
5639 
5641 {
5642  for (GameObjectList::const_iterator itr = m_gameObj.begin(); itr != m_gameObj.end(); ++itr)
5643  if (GameObject* go = ObjectAccessor::GetGameObject(*this, *itr))
5644  if (go->GetSpellId() == spellId)
5645  return go;
5646 
5647  return nullptr;
5648 }
5649 
5651 {
5652  if (!gameObj || gameObj->GetOwnerGUID())
5653  return;
5654 
5655  m_gameObj.push_back(gameObj->GetGUID());
5656  gameObj->SetOwnerGUID(GetGUID());
5657 
5658  if (GetTypeId() == TYPEID_PLAYER && gameObj->GetSpellId())
5659  {
5660  SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(gameObj->GetSpellId());
5661  // Need disable spell use for owner
5662  if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
5663  // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
5664  ToPlayer()->AddSpellAndCategoryCooldowns(createBySpell, 0, nullptr, true);
5665  }
5666 }
5667 
5668 void Unit::RemoveGameObject(GameObject* gameObj, bool del)
5669 {
5670  if (!gameObj || gameObj->GetOwnerGUID() != GetGUID())
5671  return;
5672 
5673  gameObj->SetOwnerGUID(ObjectGuid::Empty);
5674 
5675  for (uint8 i = 0; i < MAX_GAMEOBJECT_SLOT; ++i)
5676  {
5677  if (m_ObjectSlot[i] == gameObj->GetGUID())
5678  {
5679  m_ObjectSlot[i].Clear();
5680  break;
5681  }
5682  }
5683 
5684  // GO created by some spell
5685  if (uint32 spellid = gameObj->GetSpellId())
5686  {
5687  RemoveAurasDueToSpell(spellid);
5688 
5689  if (GetTypeId() == TYPEID_PLAYER)
5690  {
5691  SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(spellid);
5692  // Need activate spell use for owner
5693  if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
5694  // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
5695  ToPlayer()->SendCooldownEvent(createBySpell);
5696  }
5697  }
5698 
5699  m_gameObj.remove(gameObj->GetGUID());
5700 
5701  if (del)
5702  {
5703  gameObj->SetRespawnTime(0);
5704  gameObj->Delete();
5705  }
5706 }
5707 
5708 void Unit::RemoveGameObject(uint32 spellid, bool del)
5709 {
5710  if (m_gameObj.empty())
5711  return;
5712 
5713  for (GameObjectList::iterator itr = m_gameObj.begin(); itr != m_gameObj.end();)
5714  {
5715  if (GameObject* go = ObjectAccessor::GetGameObject(*this, *itr))
5716  {
5717  if (spellid > 0 && go->GetSpellId() != spellid)
5718  {
5719  ++itr;
5720  continue;
5721  }
5722 
5723  go->SetOwnerGUID(ObjectGuid::Empty);
5724  if(del)
5725  {
5726  go->SetRespawnTime(0);
5727  go->Delete();
5728  }
5729  }
5730  m_gameObj.erase(itr++);
5731  }
5732 }
5733 
5735 {
5736  while(!m_gameObj.empty())
5737  {
5738  GameObject* go = ObjectAccessor::GetGameObject(*this, *m_gameObj.begin());
5739  if(go)
5740  {
5742  go->SetRespawnTime(0);
5743  go->Delete();
5744  }
5745  m_gameObj.erase(m_gameObj.begin());
5746  }
5747 }
5748 
5750 {
5751  // Xinef: function for players only, placed in unit because of cosmetics
5752  if (GetTypeId() != TYPEID_PLAYER)
5753  return;
5754 
5755  WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16 + 4 + 4 + 4 + 1 + 4 + 4 + 1 + 1 + 4 + 4 + 1)); // we guess size
5756  //IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
5757  uint32 damage = log->damage;
5758  uint32 absorb = log->absorb;
5759  if (log->target->GetTypeId() == TYPEID_PLAYER && log->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
5760  {
5761  absorb = damage;
5762  damage = 0;
5763  }
5764  data << log->target->GetPackGUID();
5765  data << attacker->GetPackGUID();
5766  data << uint32(log->spellInfo->Id);
5767  data << uint32(damage); // damage amount
5768  int32 overkill = damage - log->target->GetHealth();
5769  data << uint32(overkill > 0 ? overkill : 0); // overkill
5770  data << uint8 (log->schoolMask); // damage school
5771  data << uint32(absorb); // AbsorbedDamage
5772  data << uint32(log->resist); // resist
5773  data << uint8 (log->physicalLog); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name
5774  data << uint8 (log->unused); // unused
5775  data << uint32(log->blocked); // blocked
5776  data << uint32(log->HitInfo);
5777  data << uint8 (0); // flag to use extend data
5779 }
5780 
5782 {
5783  WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16 + 4 + 4 + 4 + 1 + 4 + 4 + 1 + 1 + 4 + 4 + 1)); // we guess size
5784  //IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
5785  uint32 damage = log->damage;
5786  uint32 absorb = log->absorb;
5787  if (log->target->GetTypeId() == TYPEID_PLAYER && log->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
5788  {
5789  absorb = damage;
5790  damage = 0;
5791  }
5792  data << log->target->GetPackGUID();
5793  data << log->attacker->GetPackGUID();
5794  data << uint32(log->spellInfo->Id);
5795  data << uint32(damage); // damage amount
5796  int32 overkill = damage - log->target->GetHealth();
5797  data << uint32(overkill > 0 ? overkill : 0); // overkill
5798  data << uint8 (log->schoolMask); // damage school
5799  data << uint32(absorb); // AbsorbedDamage
5800  data << uint32(log->resist); // resist
5801  data << uint8 (log->physicalLog); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name
5802  data << uint8 (log->unused); // unused
5803  data << uint32(log->blocked); // blocked
5804  data << uint32(log->HitInfo);
5805  data << uint8 (0); // flag to use extend data
5806  SendMessageToSet(&data, true);
5807 }
5808 
5809 void Unit::SendSpellNonMeleeDamageLog(Unit* target, SpellInfo const* spellInfo, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
5810 {
5811  SpellNonMeleeDamage log(this, target, spellInfo, damageSchoolMask);
5812  log.damage = Damage;
5813  log.absorb = AbsorbedDamage;
5814  log.resist = Resist;
5815  log.physicalLog = PhysicalDamage;
5816  log.blocked = Blocked;
5818  if (CriticalHit)
5819  log.HitInfo |= SPELL_HIT_TYPE_CRIT;
5821 }
5822 
5823 void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpellInfo, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo)
5824 {
5825  // Not much to do if no flags are set.
5826  if (procAttacker)
5827  ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo);
5828  // Now go on with a victim's events'n'auras
5829  // Not much to do if no flags are set or there is no victim
5830  if (victim && victim->IsAlive() && procVictim)
5831  victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpellInfo, amount, procAura, procAuraEffectIndex, procSpell, damageInfo, healInfo);
5832 }
5833 
5835 {
5836  AuraEffect const* aura = pInfo->auraEff;
5838  data << GetPackGUID();
5839  data << aura->GetCasterGUID().WriteAsPacked();
5840  data << uint32(aura->GetId()); // spellId
5841  data << uint32(1); // count
5842  data << uint32(aura->GetAuraType()); // auraId
5843  switch (aura->GetAuraType())
5844  {
5847  {
5848  //IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
5849  uint32 damage = pInfo->damage;
5850  uint32 absorb = pInfo->absorb;
5851  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetCommandStatus(CHEAT_GOD))
5852  {
5853  absorb = damage;
5854  damage = 0;
5855  }
5856 
5857  data << uint32(damage); // damage
5858  data << uint32(pInfo->overDamage); // overkill?
5859  data << uint32(aura->GetSpellInfo()->GetSchoolMask());
5860  data << uint32(absorb); // absorb
5861  data << uint32(pInfo->resist); // resist
5862  data << uint8(pInfo->critical); // new 3.1.2 critical tick
5863  }
5864  break;
5867  data << uint32(pInfo->damage); // damage
5868  data << uint32(pInfo->overDamage); // overheal
5869  data << uint32(pInfo->absorb); // absorb
5870  data << uint8(pInfo->critical); // new 3.1.2 critical tick
5871  break;
5874  data << uint32(aura->GetMiscValue()); // power type
5875  data << uint32(pInfo->damage); // damage
5876  break;
5878  data << uint32(aura->GetMiscValue()); // power type
5879  data << uint32(pInfo->damage); // amount
5880  data << float(pInfo->multiplier); // gain multiplier
5881  break;
5882  default:
5883  LOG_ERROR("entities.unit", "Unit::SendPeriodicAuraLog: unknown aura %u", uint32(aura->GetAuraType()));
5884  return;
5885  }
5886 
5887  SendMessageToSet(&data, true);
5888 }
5889 
5890 void Unit::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
5891 {
5892  WorldPacket data(SMSG_SPELLLOGMISS, (4 + 8 + 1 + 4 + 8 + 1));
5893  data << uint32(spellID);
5894  data << GetGUID();
5895  data << uint8(0); // can be 0 or 1
5896  data << uint32(1); // target count
5897  // for (i = 0; i < target count; ++i)
5898  data << target->GetGUID(); // target GUID
5899  data << uint8(missInfo);
5900  // end loop
5901  SendMessageToSet(&data, true);
5902 }
5903 
5905 {
5906  WorldPacket data(SMSG_PROCRESIST, 8 + 8 + 4 + 1);
5907  data << GetGUID();
5908  data << target->GetGUID();
5909  data << uint32(spellId);
5910  data << uint8(0); // bool - log format: 0-default, 1-debug
5911  SendMessageToSet(&data, true);
5912 }
5913 
5915 {
5916  WorldPacket data(SMSG_SPELLORDAMAGE_IMMUNE, 8 + 8 + 4 + 1);
5917  data << GetGUID();
5918  data << target->GetGUID();
5919  data << uint32(spellId);
5920  data << uint8(0); // bool - log format: 0-default, 1-debug
5921  SendMessageToSet(&data, true);
5922 }
5923 
5925 {
5926  LOG_DEBUG("entities.unit", "WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
5927 
5928  //IF we are in cheat mode we swap absorb with damage and set damage to 0, this way we can still debug damage but our hp bar will not drop
5929  uint32 damage = damageInfo->damage;
5930  uint32 absorb = damageInfo->absorb;
5931  if (damageInfo->target->GetTypeId() == TYPEID_PLAYER && damageInfo->target->ToPlayer()->GetCommandStatus(CHEAT_GOD))
5932  {
5933  absorb = damage;
5934  damage = 0;
5935  }
5936 
5937  uint32 count = 1;
5938  size_t maxsize = 4 + 5 + 5 + 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 * 12;
5939  WorldPacket data(SMSG_ATTACKERSTATEUPDATE, maxsize); // we guess size
5940  data << uint32(damageInfo->HitInfo);
5941  data << damageInfo->attacker->GetPackGUID();
5942  data << damageInfo->target->GetPackGUID();
5943  data << uint32(damage); // Full damage
5944  int32 overkill = damage - damageInfo->target->GetHealth();
5945  data << uint32(overkill < 0 ? 0 : overkill); // Overkill
5946  data << uint8(count); // Sub damage count
5947 
5948  for (uint32 i = 0; i < count; ++i)
5949  {
5950  data << uint32(damageInfo->damageSchoolMask); // School of sub damage
5951  data << float(damage); // sub damage
5952  data << uint32(damage); // Sub Damage
5953  }
5954 
5955  if (damageInfo->HitInfo & (HITINFO_FULL_ABSORB | HITINFO_PARTIAL_ABSORB))
5956  {
5957  for (uint32 i = 0; i < count; ++i)
5958  data << uint32(absorb); // Absorb
5959  }
5960 
5961  if (damageInfo->HitInfo & (HITINFO_FULL_RESIST | HITINFO_PARTIAL_RESIST))
5962  {
5963  for (uint32 i = 0; i < count; ++i)
5964  data << uint32(damageInfo->resist); // Resist
5965  }
5966 
5967  data << uint8(damageInfo->TargetState);
5968  data << uint32(0); // Unknown attackerstate
5969  data << uint32(0); // Melee spellid
5970 
5971  if (damageInfo->HitInfo & HITINFO_BLOCK)
5972  data << uint32(damageInfo->blocked_amount);
5973 
5974  if (damageInfo->HitInfo & HITINFO_RAGE_GAIN)
5975  data << uint32(0);
5976 
5978  if (damageInfo->HitInfo & HITINFO_UNK1)
5979  {
5980  data << uint32(0);
5981  data << float(0);
5982  data << float(0);
5983  data << float(0);
5984  data << float(0);
5985  data << float(0);
5986  data << float(0);
5987  data << float(0);
5988  data << float(0);
5989  data << float(0); // Found in a loop with 1 iteration
5990  data << float(0); // ditto ^
5991  data << uint32(0);
5992  }
5993 
5994  SendMessageToSet(&data, true);
5995 }
5996 
5997 void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType*/, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount)
5998 {
5999  CalcDamageInfo dmgInfo;
6000  dmgInfo.HitInfo = HitInfo;
6001  dmgInfo.attacker = this;
6002  dmgInfo.target = target;
6003  dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
6004  dmgInfo.damageSchoolMask = damageSchoolMask;
6005  dmgInfo.absorb = AbsorbDamage;
6006  dmgInfo.resist = Resist;
6007  dmgInfo.TargetState = TargetState;
6008  dmgInfo.blocked_amount = BlockedAmount;
6009  SendAttackStateUpdate(&dmgInfo);
6010 }
6011 
6012 //victim may be nullptr
6013 bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
6014 {
6015  SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
6016  uint32 effIndex = triggeredByAura->GetEffIndex();
6017  int32 triggerAmount = triggeredByAura->GetAmount();
6018 
6019  Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
6020  ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : nullptr;
6021 
6022  uint32 triggered_spell_id = 0;
6023  uint32 cooldown_spell_id = 0; // for random trigger, will be one of the triggered spell to avoid repeatable triggers
6024  // otherwise, it's the triggered_spell_id by default
6025  Unit* target = victim;
6026  int32 basepoints0 = 0;
6027  ObjectGuid originalCaster;
6028 
6029  switch (dummySpell->SpellFamilyName)
6030  {
6031  case SPELLFAMILY_GENERIC:
6032  {
6033  switch (dummySpell->Id)
6034  {
6035  // Overkill
6036  case 58426:
6037  {
6038  triggered_spell_id = 58427;
6039  break;
6040  }
6041  // Unstable Power
6042  case 24658:
6043  {
6044  if (!procSpell || procSpell->Id == 24659)
6045  return false;
6046  // Need remove one 24659 aura
6047  RemoveAuraFromStack(24659);
6048  return true;
6049  }
6050  // Restless Strength
6051  case 24661:
6052  {
6053  // Need remove one 24662 aura
6054  RemoveAuraFromStack(24662);
6055  return true;
6056  }
6057  // Mark of Malice
6058  case 33493:
6059  {
6060  if (triggeredByAura->GetBase()->GetCharges() > 1)
6061  return true;
6062 
6063  target = this;
6064  triggered_spell_id = 33494;
6065  break;
6066  }
6067  // Twisted Reflection (boss spell)
6068  case 21063:
6069  triggered_spell_id = 21064;
6070  break;
6071  // Vampiric Aura (boss spell)
6072  case 38196:
6073  {
6074  basepoints0 = 3 * damage; // 300%
6075  if (basepoints0 < 0)
6076  return false;
6077 
6078  triggered_spell_id = 31285;
6079  target = this;
6080  break;
6081  }
6082  // Aura of Madness (Darkmoon Card: Madness trinket)
6083  //=====================================================
6084  // 39511 Sociopath: +35 strength (Paladin, Rogue, Druid, Warrior)
6085  // 40997 Delusional: +70 attack power (Rogue, Hunter, Paladin, Warrior, Druid)
6086  // 40998 Kleptomania: +35 agility (Warrior, Rogue, Paladin, Hunter, Druid)
6087  // 40999 Megalomania: +41 damage/healing (Druid, Shaman, Priest, Warlock, Mage, Paladin)
6088  // 41002 Paranoia: +35 spell/melee/ranged crit strike rating (All classes)
6089  // 41005 Manic: +35 haste (spell, melee and ranged) (All classes)
6090  // 41009 Narcissism: +35 intellect (Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter)
6091  // 41011 Martyr Complex: +35 stamina (All classes)
6092  // 41406 Dementia: Every 5 seconds either gives you +5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
6093  // 41409 Dementia: Every 5 seconds either gives you -5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
6094  case 39446:
6095  {
6096  if (GetTypeId() != TYPEID_PLAYER || !IsAlive())
6097  return false;
6098 
6099  // Select class defined buff
6100  switch (getClass())
6101  {
6102  case CLASS_PALADIN: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
6103  case CLASS_DRUID: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
6104  triggered_spell_id = RAND(39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409);
6105  cooldown_spell_id = 39511;
6106  break;
6107  case CLASS_ROGUE: // 39511, 40997, 40998, 41002, 41005, 41011
6108  case CLASS_WARRIOR: // 39511, 40997, 40998, 41002, 41005, 41011
6109  case CLASS_DEATH_KNIGHT:
6110  triggered_spell_id = RAND(39511, 40997, 40998, 41002, 41005, 41011);
6111  cooldown_spell_id = 39511;
6112  break;
6113  case CLASS_PRIEST: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
6114  case CLASS_SHAMAN: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
6115  case CLASS_MAGE: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
6116  case CLASS_WARLOCK: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
6117  triggered_spell_id = RAND(40999, 41002, 41005, 41009, 41011, 41406, 41409);
6118  cooldown_spell_id = 40999;
6119  break;
6120  case CLASS_HUNTER: // 40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409
6121  triggered_spell_id = RAND(40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409);
6122  cooldown_spell_id = 40997;
6123  break;
6124  default:
6125  return false;
6126  }
6127 
6128  target = this;
6129  if (roll_chance_i(10))
6130  ToPlayer()->Say("This is Madness!", LANG_UNIVERSAL); // TODO: It should be moved to database, shouldn't it?
6131  break;
6132  }
6133  // Sunwell Exalted Caster Neck (??? neck)
6134  // cast ??? Light's Wrath if Exalted by Aldor
6135  // cast ??? Arcane Bolt if Exalted by Scryers
6136  case 46569:
6137  return false; // old unused version
6138  // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck)
6139  // cast 45479 Light's Wrath if Exalted by Aldor
6140  // cast 45429 Arcane Bolt if Exalted by Scryers
6141  case 45481:
6142  {
6143  Player* player = ToPlayer();
6144  if (!player)
6145  return false;
6146 
6147  // Get Aldor reputation rank
6148  if (player->GetReputationRank(932) == REP_EXALTED)
6149  {
6150  target = this;
6151  triggered_spell_id = 45479;
6152  break;
6153  }
6154  // Get Scryers reputation rank
6155  if (player->GetReputationRank(934) == REP_EXALTED)
6156  {
6157  // triggered at positive/self casts also, current attack target used then
6158  if (target && IsFriendlyTo(target))
6159  {
6160  target = GetVictim();
6161  if (!target)
6162  {
6163  target = player->GetSelectedUnit();
6164  if (!target)
6165  return false;
6166  }
6167  if (IsFriendlyTo(target))
6168  return false;
6169  }
6170 
6171  triggered_spell_id = 45429;
6172  break;
6173  }
6174  return false;
6175  }
6176  // Sunwell Exalted Melee Neck (Shattered Sun Pendant of Might neck)
6177  // cast 45480 Light's Strength if Exalted by Aldor
6178  // cast 45428 Arcane Strike if Exalted by Scryers
6179  case 45482:
6180  {
6181  if (GetTypeId() != TYPEID_PLAYER)
6182  return false;
6183 
6184  // Get Aldor reputation rank
6185  if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
6186  {
6187  target = this;
6188  triggered_spell_id = 45480;
6189  break;
6190  }
6191  // Get Scryers reputation rank
6192  if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
6193  {
6194  triggered_spell_id = 45428;
6195  break;
6196  }
6197  return false;
6198  }
6199  // Sunwell Exalted Tank Neck (Shattered Sun Pendant of Resolve neck)
6200  // cast 45431 Arcane Insight if Exalted by Aldor
6201  // cast 45432 Light's Ward if Exalted by Scryers
6202  case 45483:
6203  {
6204  if (GetTypeId() != TYPEID_PLAYER)
6205  return false;
6206 
6207  // Get Aldor reputation rank
6208  if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
6209  {
6210  target = this;
6211  triggered_spell_id = 45432;
6212  break;
6213  }
6214  // Get Scryers reputation rank
6215  if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
6216  {
6217  target = this;
6218  triggered_spell_id = 45431;
6219  break;
6220  }
6221  return false;
6222  }
6223  // Sunwell Exalted Healer Neck (Shattered Sun Pendant of Restoration neck)
6224  // cast 45478 Light's Salvation if Exalted by Aldor
6225  // cast 45430 Arcane Surge if Exalted by Scryers
6226  case 45484:
6227  {
6228  if (GetTypeId() != TYPEID_PLAYER)
6229  return false;
6230 
6231  // Get Aldor reputation rank
6232  if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
6233  {
6234  target = this;
6235  triggered_spell_id = 45478;
6236  break;
6237  }
6238  // Get Scryers reputation rank
6239  if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
6240  {
6241  triggered_spell_id = 45430;
6242  break;
6243  }
6244  return false;
6245  }
6246  // Kill command
6247  case 58914:
6248  {
6249  // Remove aura stack from pet
6250  RemoveAuraFromStack(58914);
6251  Unit* owner = GetOwner();
6252  if (!owner)
6253  return true;
6254  // reduce the owner's aura stack
6255  owner->RemoveAuraFromStack(34027);
6256  return true;
6257  }
6258  // Vampiric Touch (generic, used by some boss)
6259  case 52723:
6260  case 60501:
6261  {
6262  triggered_spell_id = 52724;
6263  basepoints0 = damage / 2;
6264  target = this;
6265  break;
6266  }
6267  // Divine purpose
6268  case 31871:
6269  case 31872:
6270  {
6271  // Roll chane
6272  if (!victim || !victim->IsAlive() || !roll_chance_i(triggerAmount))
6273  return false;
6274 
6275  // Remove any stun effect on target
6277  return true;
6278  }
6279  // Glyph of Life Tap
6280  case 63320:
6281  {
6282  triggered_spell_id = 63321; // Life Tap
6283  break;
6284  }
6285  case 71519: // Deathbringer's Will Normal
6286  {
6287  if (GetTypeId() != TYPEID_PLAYER || HasSpellCooldown(71484))
6288  return false;
6289 
6290  AddSpellCooldown(71484, 0, cooldown);
6291 
6292  std::vector<uint32> RandomSpells;
6293  switch (getClass())
6294  {
6295  case CLASS_WARRIOR:
6296  case CLASS_PALADIN:
6297  case CLASS_DEATH_KNIGHT:
6298  RandomSpells.push_back(71484);
6299  RandomSpells.push_back(71491);
6300  RandomSpells.push_back(71492);
6301  break;
6302  case CLASS_SHAMAN:
6303  case CLASS_ROGUE:
6304  RandomSpells.push_back(71486);
6305  RandomSpells.push_back(71485);
6306  RandomSpells.push_back(71492);
6307  break;
6308  case CLASS_DRUID:
6309  RandomSpells.push_back(71484);
6310  RandomSpells.push_back(71485);
6311  RandomSpells.push_back(71492);
6312  break;
6313  case CLASS_HUNTER:
6314  RandomSpells.push_back(71486);
6315  RandomSpells.push_back(71491);
6316  RandomSpells.push_back(71485);
6317  break;
6318  default:
6319  return false;
6320  }
6321  if (RandomSpells.empty()) // shouldn't happen
6322  return false;
6323 
6324  uint8 rand_spell = irand(0, (RandomSpells.size() - 1));
6325  CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
6326  break;
6327  }
6328  case 71562: // Deathbringer's Will Heroic
6329  {
6330  if (GetTypeId() != TYPEID_PLAYER || HasSpellCooldown(71561))
6331  return false;
6332 
6333  AddSpellCooldown(71561, 0, cooldown);
6334 
6335  std::vector<uint32> RandomSpells;
6336  switch (getClass())
6337  {
6338  case CLASS_WARRIOR:
6339  case CLASS_PALADIN:
6340  case CLASS_DEATH_KNIGHT:
6341  RandomSpells.push_back(71561);
6342  RandomSpells.push_back(71559);
6343  RandomSpells.push_back(71560);
6344  break;
6345  case CLASS_SHAMAN:
6346  case CLASS_ROGUE:
6347  RandomSpells.push_back(71558);
6348  RandomSpells.push_back(71556);
6349  RandomSpells.push_back(71560);
6350  break;
6351  case CLASS_DRUID:
6352  RandomSpells.push_back(71561);
6353  RandomSpells.push_back(71556);
6354  RandomSpells.push_back(71560);
6355  break;
6356  case CLASS_HUNTER:
6357  RandomSpells.push_back(71558);
6358  RandomSpells.push_back(71559);
6359  RandomSpells.push_back(71556);
6360  break;
6361  default:
6362  return false;
6363  }
6364  if (RandomSpells.empty()) // shouldn't happen
6365  return false;
6366 
6367  uint8 rand_spell = irand(0, (RandomSpells.size() - 1));
6368  CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
6369  break;
6370  }
6371  // Freya, Petrified Bark
6372  case 62933:
6373  case 62337:
6374  {
6375  if (!victim)
6376  return false;
6377 
6378  int32 dmg = damage;
6379  victim->CastCustomSpell(this, 62379, &dmg, 0, 0, true);
6380  return true;
6381  }
6382  // Trial of the Champion, Earth Shield
6383  case 67534:
6384  {
6385  const int32 dmg = (int32)damage;
6386  CastCustomSpell(this, 67535, &dmg, nullptr, nullptr, true, 0, triggeredByAura, triggeredByAura->GetCasterGUID());
6387  return true;
6388  }
6389  // Trial of the Crusader, Faction Champions, Retaliation
6390  case 65932:
6391  {
6392  // check attack comes not from behind
6393  if (!victim || !HasInArc(M_PI, victim))
6394  return false;
6395 
6396  triggered_spell_id = 65934;
6397  break;
6398  }
6399  // Pit of Saron, Tyrannus, Overlord's Brand
6400  case 69172: // everything except for DoTs
6401  {
6402  if (!target)
6403  return false;
6404  if (Unit* caster = triggeredByAura->GetCaster())
6405  {
6407  {
6408  int32 dmg = 5.5f * damage;
6409  target->CastCustomSpell(caster, 69190, &dmg, 0, 0, true);
6410  }
6411  else
6412  {
6413  if (caster->GetVictim())
6414  {
6415  int32 dmg = damage;
6416  target->CastCustomSpell(caster->GetVictim(), 69189, &dmg, 0, 0, true);
6417  }
6418  }
6419  }
6420  return true;
6421  }
6422  // Pit of Saron, Tyrannus, Overlord's Brand
6423  case 69173: // only DoTs
6424  {
6425  if (!target)
6426  return false;
6427  if (Unit* caster = triggeredByAura->GetCaster())
6428  {
6429  if (procEx & PROC_EX_INTERNAL_HOT)
6430  {
6431  int32 dmg = 5.5f * damage;
6432  target->CastCustomSpell(caster, 69190, &dmg, 0, 0, true);
6433  }
6434  else
6435  {
6436  if (caster->GetVictim())
6437  {
6438  int32 dmg = damage;
6439  target->CastCustomSpell(caster->GetVictim(), 69189, &dmg, 0, 0, true);
6440  }
6441  }
6442  }
6443  return true;
6444  }
6445  // Icecrown Citadel, Lady Deathwhisper, Vampiric Might
6446  case 70674:
6447  {
6448  if (Unit* caster = triggeredByAura->GetCaster())
6449  {
6450  int32 dmg = 3 * damage;
6451  caster->CastCustomSpell(caster, 70677, &dmg, 0, 0, true);
6452  }
6453  return true;
6454  }
6455  // Item: Purified Shard of the Gods
6456  case 69755:
6457  {
6458  triggered_spell_id = ((procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69733 : 69729);
6459  break;
6460  }
6461  // Item: Shiny Shard of the Gods
6462  case 69739:
6463  {
6464  triggered_spell_id = ((procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69734 : 69730);
6465  break;
6466  }
6467  // VoA: Meteor Fists koralon
6468  case 66725:
6469  case 68161:
6470  {
6471  triggered_spell_id = 66765; // handled by spell_difficulty
6472  break;
6473  }
6474  }
6475  break;
6476  }
6477  case SPELLFAMILY_MAGE:
6478  {
6479  // Magic Absorption
6480  if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
6481  {
6482  if (getPowerType() != POWER_MANA)
6483  return false;
6484 
6485  // mana reward
6486  basepoints0 = CalculatePct(int32(GetMaxPower(POWER_MANA)), triggerAmount);
6487  target = this;
6488  triggered_spell_id = 29442;
6489  break;
6490  }
6491  // Hot Streak
6492  if (dummySpell->SpellIconID == 2999)
6493  {
6494  if (effIndex != 0)
6495  return false;
6496  AuraEffect* counter = triggeredByAura->GetBase()->GetEffect(EFFECT_1);
6497  if (!counter)
6498  return true;
6499 
6500  // Count spell criticals in a row in second aura
6501  if (procEx & PROC_EX_CRITICAL_HIT)
6502  {
6503  counter->SetAmount(counter->GetAmount() * 2);
6504  if (counter->GetAmount() < 100) // not enough
6505  return true;
6506  // Crititcal counted -> roll chance
6507  if (roll_chance_i(triggerAmount))
6508  CastSpell(this, 48108, true, castItem, triggeredByAura);
6509  }
6510  counter->SetAmount(25);
6511  return true;
6512  }
6513  // Incanter's Regalia set (add trigger chance to Mana Shield)
6514  if (dummySpell->SpellFamilyFlags[0] & 0x8000)
6515  {
6516  if (GetTypeId() != TYPEID_PLAYER)
6517  return false;
6518 
6519  target = this;
6520  triggered_spell_id = 37436;
6521  break;
6522  }
6523  switch (dummySpell->Id)
6524  {
6525  // Glyph of Polymorph
6526  case 56375:
6527  {
6528  if (!target)
6529  return false;
6530  target->RemoveAurasByType(SPELL_AURA_PERIODIC_DAMAGE, ObjectGuid::Empty, target->GetAura(32409)); // SW:D shall not be removed.
6533  return true;
6534  }
6535  // Glyph of Icy Veins
6536  case 56374:
6537  {
6540  return true;
6541  }
6542  // Glyph of Ice Block
6543  case 56372:
6544  {
6545  Player* player = ToPlayer();
6546  if (!player)
6547  return false;
6548 
6549  SpellCooldowns const cooldowns = player->GetSpellCooldowns();
6550  // remove cooldowns on all ranks of Frost Nova
6551  for (SpellCooldowns::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr)
6552  {
6553  SpellInfo const* cdSpell = sSpellMgr->GetSpellInfo(itr->first);
6554  // Frost Nova
6555  if (cdSpell && cdSpell->SpellFamilyName == SPELLFAMILY_MAGE
6556  && cdSpell->SpellFamilyFlags[0] & 0x00000040)
6557  player->RemoveSpellCooldown(cdSpell->Id, true);
6558  }
6559  break;
6560  }
6561  }
6562  break;
6563  }
6564  case SPELLFAMILY_WARRIOR:
6565  {
6566  switch (dummySpell->Id)
6567  {
6568  // Victorious
6569  case 32216:
6570  {
6571  RemoveAura(dummySpell->Id);
6572  return false;
6573  }
6574  }
6575 
6576  // Second Wind
6577  if (dummySpell->SpellIconID == 1697)
6578  {
6579  // only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example)
6580  if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) || this == victim)
6581  return false;
6582  // Need stun or root mechanic
6583  if (!(procSpell->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN))))
6584  return false;
6585 
6586  switch (dummySpell->Id)
6587  {
6588  case 29838:
6589  triggered_spell_id = 29842;
6590  break;
6591  case 29834:
6592  triggered_spell_id = 29841;
6593  break;
6594  case 42770:
6595  triggered_spell_id = 42771;
6596  break;
6597  default:
6598  LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled spell id: %u (SW)", dummySpell->Id);
6599  return false;
6600  }
6601 
6602  target = this;
6603  break;
6604  }
6605  break;
6606  }
6607  case SPELLFAMILY_WARLOCK:
6608  {
6609  // Seed of Corruption
6610  if (dummySpell->SpellFamilyFlags[1] & 0x00000010)
6611  {
6612  if (procSpell && procSpell->SpellFamilyFlags[1] & 0x8000)
6613  return false;
6614  // if damage is more than need or target die from damage deal finish spell
6615  if (triggeredByAura->GetAmount() <= int32(damage) || GetHealth() <= damage)
6616  {
6617  // remember guid before aura delete
6618  ObjectGuid casterGuid = triggeredByAura->GetCasterGUID();
6619 
6620  // Remove aura (before cast for prevent infinite loop handlers)
6621  RemoveAurasDueToSpell(triggeredByAura->GetId());
6622 
6623  uint32 spell = sSpellMgr->GetSpellWithRank(27285, dummySpell->GetRank());
6624 
6625  // Cast finish spell (triggeredByAura already not exist!)
6626  if (Unit* caster = ObjectAccessor::GetUnit(*this, casterGuid))
6627  {
6628  this->CastSpell(this, 37826, true); // VISUAL!
6629  caster->CastSpell(this, spell, true, castItem);
6630  }
6631 
6632  return true; // no hidden cooldown
6633  }
6634 
6635  // Damage counting
6636  triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
6637  return true;
6638  }
6639  // Seed of Corruption (Mobs cast) - no die req
6640  if (dummySpell->SpellFamilyFlags.IsEqual(0, 0, 0) && dummySpell->SpellIconID == 1932)
6641  {
6642  // if damage is more than need deal finish spell
6643  if (triggeredByAura->GetAmount() <= int32(damage))
6644  {
6645  // remember guid before aura delete
6646  ObjectGuid casterGuid = triggeredByAura->GetCasterGUID();
6647 
6648  // Remove aura (before cast for prevent infinite loop handlers)
6649  RemoveAurasDueToSpell(triggeredByAura->GetId());
6650 
6651  // Cast finish spell (triggeredByAura already not exist!)
6652  if (Unit* caster = ObjectAccessor::GetUnit(*this, casterGuid))
6653  {
6654  this->CastSpell(this, 37826, true); // VISUAL!
6655  caster->CastSpell(this, 32865, true, castItem);
6656  }
6657  return true; // no hidden cooldown
6658  }
6659  // Damage counting
6660  triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
6661  return true;
6662  }
6663  switch (dummySpell->Id)
6664  {
6665  // Nightfall
6666  case 18094:
6667  case 18095:
6668  // Glyph of corruption
6669  case 56218:
6670  {
6671  target = this;
6672  triggered_spell_id = 17941;
6673  break;
6674  }
6675  // Soul Leech
6676  case 30293:
6677  case 30295:
6678  case 30296:
6679  {
6680  // Improved Soul Leech
6681  AuraEffectList const& SoulLeechAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
6682  for (Unit::AuraEffectList::const_iterator i = SoulLeechAuras.begin(); i != SoulLeechAuras.end(); ++i)
6683  {
6684  if ((*i)->GetId() == 54117 || (*i)->GetId() == 54118)
6685  {
6686  if ((*i)->GetEffIndex() != 0)
6687  continue;
6688  basepoints0 = int32((*i)->GetAmount());
6689  target = GetGuardianPet();
6690  if (target)
6691  {
6692  // regen mana for pet
6693  CastCustomSpell(target, 54607, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura);
6694  }
6695  // regen mana for caster
6696  CastCustomSpell(this, 59117, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura);
6697  // Get second aura of spell for replenishment effect on party
6698  if (AuraEffect const* aurEff = (*i)->GetBase()->GetEffect(EFFECT_1))
6699  {
6700  // Replenishment - roll chance
6701  if (roll_chance_i(aurEff->GetAmount()))
6702  {
6703  CastSpell(this, 57669, true, castItem, triggeredByAura);
6704  }
6705  }
6706  break;
6707  }
6708  }
6709  // health
6710  basepoints0 = CalculatePct(int32(damage), triggerAmount);
6711  target = this;
6712  triggered_spell_id = 30294;
6713  break;
6714  }
6715  // Shadowflame (Voidheart Raiment set bonus)
6716  case 37377:
6717  {
6718  triggered_spell_id = 37379;
6719  break;
6720  }
6721  // Pet Healing (Corruptor Raiment or Rift Stalker Armor)
6722  case 37381:
6723  {
6724  target = GetGuardianPet();
6725  if (!target)
6726  return false;
6727 
6728  // heal amount
6729  basepoints0 = CalculatePct(int32(damage), triggerAmount);
6730  triggered_spell_id = 37382;
6731  break;
6732  }
6733  // Shadowflame Hellfire (Voidheart Raiment set bonus)
6734  case 39437:
6735  {
6736  triggered_spell_id = 37378;
6737  break;
6738  }
6739  }
6740  break;
6741  }
6742  case SPELLFAMILY_PRIEST:
6743  {
6744  // Body and Soul
6745  if (dummySpell->SpellIconID == 2218)
6746  {
6747  // Proc only from Abolish desease on self cast
6748  if (procSpell->Id != 552 || victim != this || !roll_chance_i(triggerAmount))
6749  return false;
6750  triggered_spell_id = 64136;
6751  target = this;
6752  break;
6753  }
6754  switch (dummySpell->Id)
6755  {
6756  // Vampiric Embrace
6757  case 15286:
6758  {
6759  if (!victim || !victim->IsAlive() || procSpell->SpellFamilyFlags[1] & 0x80000)
6760  return false;
6761 
6762  // heal amount
6763  int32 total = CalculatePct(int32(damage), triggerAmount);
6764  int32 team = total / 5;
6765  int32 self = total - team;
6766  CastCustomSpell(this, 15290, &team, &self, nullptr, true, castItem, triggeredByAura);
6767  return true; // no hidden cooldown
6768  }
6769  // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
6770  case 40438:
6771  {
6772  // Shadow Word: Pain
6773  if (procSpell->SpellFamilyFlags[0] & 0x8000)
6774  triggered_spell_id = 40441;
6775  // Renew
6776  else if (procSpell->SpellFamilyFlags[0] & 0x40)
6777  triggered_spell_id = 40440;
6778  else
6779  return false;
6780 
6781  target = this;
6782  break;
6783  }
6784  // Improved Shadowform
6785  case 47570:
6786  case 47569:
6787  {
6788  if (!roll_chance_i(triggerAmount))
6789  return false;
6790 
6792  break;
6793  }
6794  // Glyph of Dispel Magic
6795  case 55677:
6796  {
6797  // Dispel Magic shares spellfamilyflag with abolish disease
6798  if (procSpell->SpellIconID != 74)
6799  return false;
6800  if (!target || !target->IsFriendlyTo(this))
6801  return false;
6802 
6803  basepoints0 = int32(target->CountPctFromMaxHealth(triggerAmount));
6804  triggered_spell_id = 56131;
6805  break;
6806  }
6807  // Oracle Healing Bonus ("Garments of the Oracle" set)
6808  case 26169:
6809  {
6810  // heal amount
6811  basepoints0 = int32(CalculatePct(damage, 10));
6812  target = this;
6813  triggered_spell_id = 26170;
6814  break;
6815  }
6816  // Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set
6817  case 39372:
6818  {
6819  if (!procSpell || (procSpell->GetSchoolMask() & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW)) == 0)
6820  return false;
6821 
6822  // heal amount
6823  basepoints0 = CalculatePct(int32(damage), triggerAmount);
6824  target = this;
6825  triggered_spell_id = 39373;
6826  break;
6827  }
6828  // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
6829  case 28809:
6830  {
6831  triggered_spell_id = 28810;
6832  break;
6833  }
6834  // Priest T10 Healer 2P Bonus
6835  case 70770:
6836  // Flash Heal
6837  if (procSpell->SpellFamilyFlags[0] & 0x800)
6838  {
6839  triggered_spell_id = 70772;
6840  SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id);
6841  if (!blessHealing || !victim)
6842  return false;
6843  basepoints0 = int32(CalculatePct(damage, triggerAmount) / (blessHealing->GetMaxDuration() / blessHealing->Effects[0].Amplitude));
6844  victim->CastDelayedSpellWithPeriodicAmount(this, triggered_spell_id, SPELL_AURA_PERIODIC_HEAL, basepoints0);
6845  return true;
6846  }
6847  break;
6848  }
6849  break;
6850  }
6851  case SPELLFAMILY_DRUID:
6852  {
6853  switch (dummySpell->Id)
6854  {
6855  // Glyph of Innervate
6856  case 54832:
6857  {
6858  if (procSpell->SpellIconID != 62)
6859  return false;
6860 
6861  int32 mana_perc = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcValue();
6862  basepoints0 = int32(CalculatePct(GetCreatePowers(POWER_MANA), mana_perc) / 10);
6863  triggered_spell_id = 54833;
6864  target = this;
6865  break;
6866  }
6867  // Glyph of Starfire
6868  case 54845:
6869  {
6870  triggered_spell_id = 54846;
6871  break;
6872  }
6873  // Glyph of Shred
6874  case 54815:
6875  {
6876  if (!target)
6877  return false;
6878 
6879  // try to find spell Rip on the target
6880  if (AuraEffect const* AurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00800000, 0x0, 0x0, GetGUID()))
6881  {
6882  // Rip's max duration, note: spells which modifies Rip's duration also counted like Glyph of Rip
6883  uint32 CountMin = AurEff->GetBase()->GetMaxDuration();
6884 
6885  // just Rip's max duration without other spells
6886  uint32 CountMax = AurEff->GetSpellInfo()->GetMaxDuration();
6887 
6888  // add possible auras' and Glyph of Shred's max duration
6889  CountMax += 3 * triggerAmount * IN_MILLISECONDS; // Glyph of Shred -> +6 seconds
6890  CountMax += HasAura(54818) ? 4 * IN_MILLISECONDS : 0; // Glyph of Rip -> +4 seconds
6891  CountMax += HasAura(60141) ? 4 * IN_MILLISECONDS : 0; // Rip Duration/Lacerate Damage -> +4 seconds
6892 
6893  // if min < max -> that means caster didn't cast 3 shred yet
6894  // so set Rip's duration and max duration
6895  if (CountMin < CountMax)
6896  {
6897  AurEff->GetBase()->SetDuration(AurEff->GetBase()->GetDuration() + triggerAmount * IN_MILLISECONDS);
6898  AurEff->GetBase()->SetMaxDuration(CountMin + triggerAmount * IN_MILLISECONDS);
6899  return true;
6900  }
6901  }
6902  // if not found Rip
6903  return false;
6904  }
6905  // Glyph of Rake
6906  case 54821:
6907  {
6908  if (procSpell->SpellVisual[0] == 750 && procSpell->Effects[1].ApplyAuraName == 3)
6909  {
6910  if (target && target->GetTypeId() == TYPEID_UNIT)
6911  {
6912  triggered_spell_id = 54820;
6913  break;
6914  }
6915  }
6916  return false;
6917  }
6918  // Leader of the Pack
6919  case 24932:
6920  {
6921  if (triggerAmount <= 0)
6922  return false;
6923  basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
6924  target = this;
6925  triggered_spell_id = 34299;
6926  if (triggeredByAura->GetCasterGUID() != GetGUID())
6927  break;
6928  int32 basepoints1 = CalculatePct(GetMaxPower(Powers(POWER_MANA)), triggerAmount * 2);
6929  // Improved Leader of the Pack
6930  // Check cooldown of heal spell cooldown
6931  if (GetTypeId() == TYPEID_PLAYER && !ToPlayer()->HasSpellCooldown(34299))
6932  CastCustomSpell(this, 68285, &basepoints1, 0, 0, true, 0, triggeredByAura);
6933  break;
6934  }
6935  // Healing Touch (Dreamwalker Raiment set)
6936  case 28719:
6937  {
6938  // mana back
6939  basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
6940  target = this;
6941  triggered_spell_id = 28742;
6942  break;
6943  }
6944  // Glyph of Rejuvenation
6945  case 54754:
6946  {
6947  if (!victim || !victim->HealthBelowPct(uint32(triggerAmount)))
6948  return false;
6949  basepoints0 = CalculatePct(int32(damage), triggerAmount);
6950  triggered_spell_id = 54755;
6951  break;
6952  }
6953  // Healing Touch Refund (Idol of Longevity trinket)
6954  case 28847:
6955  {
6956  target = this;
6957  triggered_spell_id = 28848;
6958  break;
6959  }
6960  // Mana Restore (Malorne Raiment set / Malorne Regalia set)
6961  case 37288:
6962  case 37295:
6963  {
6964  target = this;
6965  triggered_spell_id = 37238;
6966  break;
6967  }
6968  // Druid Tier 6 Trinket
6969  case 40442:
6970  {
6971  float chance;
6972 
6973  // Starfire
6974  if (procSpell->SpellFamilyFlags[0] & 0x4)
6975  {
6976  triggered_spell_id = 40445;
6977  chance = 25.0f;
6978  }
6979  // Rejuvenation
6980  else if (procSpell->SpellFamilyFlags[0] & 0x10)
6981  {
6982  triggered_spell_id = 40446;
6983  chance = 25.0f;
6984  }
6985  // Mangle (Bear) and Mangle (Cat)
6986  else if (procSpell->SpellFamilyFlags[1] & 0x00000440)
6987  {
6988  triggered_spell_id = 40452;
6989  chance = 40.0f;
6990  }
6991  else
6992  return false;
6993 
6994  if (!roll_chance_f(chance))
6995  return false;
6996 
6997  target = this;
6998  break;
6999  }
7000  // Maim Interrupt
7001  case 44835:
7002  {
7003  // Deadly Interrupt Effect
7004  triggered_spell_id = 32747;
7005  break;
7006  }
7007  // Item - Druid T10 Restoration 4P Bonus (Rejuvenation)
7008  case 70664:
7009  {
7010  // xinef: proc only from normal Rejuvenation, and proc rejuvenation
7011  if (!victim || !procSpell || procSpell->SpellIconID != 64)
7012  return false;
7013 
7014  Player* caster = ToPlayer();
7015  if (!caster)
7016  return false;
7017  if (!caster->GetGroup() && victim == this)
7018  return false;
7019 
7020  CastCustomSpell(70691, SPELLVALUE_BASE_POINT0, damage, victim, true);
7021  return true;
7022  }
7023  }
7024  // Eclipse
7025  if (dummySpell->SpellIconID == 2856 && GetTypeId() == TYPEID_PLAYER)
7026  {
7027  if (!procSpell || effIndex != 0)
7028  return false;
7029 
7030  bool isWrathSpell = (procSpell->SpellFamilyFlags[0] & 1);
7031 
7032  if (!roll_chance_f(dummySpell->ProcChance * (isWrathSpell ? 0.6f : 1.0f)))
7033  return false;
7034 
7035  target = this;
7036  if (target->HasAura(isWrathSpell ? 48517 : 48518))
7037  return false;
7038 
7039  triggered_spell_id = isWrathSpell ? 48518 : 48517;
7040  break;
7041  }
7042  [[fallthrough]]; // TODO: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
7043  }
7044  case SPELLFAMILY_ROGUE:
7045  {
7046  switch(dummySpell->Id)
7047  {
7048  // Glyph of Backstab
7049  case 56800:
7050  {
7051  if (victim)
7052  if (AuraEffect* aurEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x100000, 0, 0, GetGUID()))
7053  if (Aura* aur = aurEff->GetBase())
7054  if (!aur->IsRemoved() && aur->GetDuration() > 0)
7055  if ((aur->GetApplyTime() + aur->GetMaxDuration() / 1000 + 5) > (time(nullptr) + aur->GetDuration() / 1000) )
7056  {
7057  aur->SetDuration(aur->GetDuration() + 2000);
7058  return true;
7059  }
7060  return false;
7061  }
7062  // Deadly Throw Interrupt
7063  case 32748:
7064  {
7065  // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw
7066  if (this == victim)
7067  return false;
7068 
7069  triggered_spell_id = 32747;
7070  break;
7071  }
7072  }
7073  // Master of subtlety
7074  if( dummySpell->SpellIconID == 2114 )
7075  {
7076  triggered_spell_id = 31665;
7077  basepoints0 = triggerAmount;
7078  break;
7079  }
7080  // Cut to the Chase
7081  if (dummySpell->SpellIconID == 2909)
7082  {
7083  // "refresh your Slice and Dice duration to its 5 combo point maximum"
7084  // lookup Slice and Dice
7085  if (AuraEffect const* aur = GetAuraEffect(SPELL_AURA_MOD_MELEE_HASTE, SPELLFAMILY_ROGUE, 0x40000, 0, 0))
7086  {
7087  aur->GetBase()->SetDuration(aur->GetSpellInfo()->GetMaxDuration(), true);
7088  return true;
7089  }
7090  return false;
7091  }
7092  // Deadly Brew
7093  else if (dummySpell->SpellIconID == 2963)
7094  {
7095  triggered_spell_id = 3409;
7096  break;
7097  }
7098  // Quick Recovery
7099  else if (dummySpell->SpellIconID == 2116)
7100  {
7101  if (!procSpell)
7102  return false;
7103 
7104  // energy cost save
7105  basepoints0 = CalculatePct(int32(procSpell->ManaCost), triggerAmount);
7106  if (basepoints0 <= 0)
7107  return false;
7108 
7109  target = this;
7110  triggered_spell_id = 31663;
7111  break;
7112  }
7113  break;
7114  }
7115  case SPELLFAMILY_HUNTER:
7116  {
7117  switch (dummySpell->SpellIconID)
7118  {
7119  case 2236: // Thrill of the Hunt
7120  {
7121  if (!procSpell)
7122  return false;
7123 
7124  Spell* spell = ToPlayer()->m_spellModTakingSpell;
7125 
7126  // Disable charge drop because of Lock and Load
7127  if (spell)
7128  ToPlayer()->SetSpellModTakingSpell(spell, false);
7129 
7130  // Explosive Shot
7131  if (procSpell->SpellFamilyFlags[2] & 0x200)
7132  {
7133  if (!victim)
7134  return false;
7135  if (AuraEffect const* pEff = victim->GetAuraEffect(SPELL_AURA_PERIODIC_DUMMY, SPELLFAMILY_HUNTER, 0x0, 0x80000000, 0x0, GetGUID()))
7136  basepoints0 = pEff->GetSpellInfo()->CalcPowerCost(this, SpellSchoolMask(pEff->GetSpellInfo()->SchoolMask)) * 4 / 10 / 3;
7137  }
7138  else
7139  basepoints0 = procSpell->CalcPowerCost(this, SpellSchoolMask(procSpell->SchoolMask)) * 4 / 10;
7140 
7141  if (spell)
7142  ToPlayer()->SetSpellModTakingSpell(spell, true);
7143 
7144  if (basepoints0 <= 0)
7145  return false;
7146 
7147  target = this;
7148  triggered_spell_id = 34720;
7149  break;
7150  }
7151  case 3406: // Hunting Party
7152  {
7153  triggered_spell_id = 57669;
7154  target = this;
7155  break;
7156  }
7157  case 3560: // Rapid Recuperation
7158  {
7159  // This effect only from Rapid Killing (mana regen)
7160  if (!(procSpell->SpellFamilyFlags[1] & 0x01000000))
7161  return false;
7162 
7163  target = this;
7164 
7165  switch (dummySpell->Id)
7166  {
7167  case 53228: // Rank 1
7168  triggered_spell_id = 56654;
7169  break;
7170  case 53232: // Rank 2
7171  triggered_spell_id = 58882;
7172  break;
7173  }
7174  break;
7175  }
7176  }
7177 
7178  switch (dummySpell->Id)
7179  {
7180  case 57870: // Glyph of Mend Pet
7181  {
7182  if (!victim)
7183  return false;
7184 
7185  victim->CastSpell(victim, 57894, true, nullptr, nullptr, GetGUID());
7186  return true;
7187  }
7188  }
7189  break;
7190  }
7191  case SPELLFAMILY_PALADIN:
7192  {
7193  // Light's Beacon - Beacon of Light
7194  if (dummySpell->Id == 53651)
7195  {
7196  if (!victim)
7197  return false;
7198 
7199  Unit* beaconTarget = triggeredByAura->GetBase()->GetCaster();
7200  if (!beaconTarget || beaconTarget == this || !beaconTarget->GetAura(53563, victim->GetGUID()))
7201  return false;
7202 
7203  basepoints0 = int32(damage);
7204  triggered_spell_id = procSpell->IsRankOf(sSpellMgr->GetSpellInfo(635)) ? 53652 : 53654;
7205 
7206  victim->CastCustomSpell(beaconTarget, triggered_spell_id, &basepoints0, nullptr, nullptr, true, 0, triggeredByAura, victim->GetGUID());
7207  return true;
7208  }
7209  // Judgements of the Wise
7210  if (dummySpell->SpellIconID == 3017)
7211  {
7212  target = this;
7213  triggered_spell_id = 31930;
7214  // replenishment
7215  CastSpell(this, 57669, true, castItem, triggeredByAura);
7216  break;
7217  }
7218  // Righteous Vengeance
7219  if (dummySpell->SpellIconID == 3025)
7220  {
7221  if (!victim)
7222  return false;
7223 
7224  // 4 damage tick
7225  basepoints0 = triggerAmount * damage / 400;
7226  triggered_spell_id = 61840;
7227  // Add remaining ticks to damage done
7228  victim->CastDelayedSpellWithPeriodicAmount(this, triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE, basepoints0);
7229  return true;
7230  }
7231  // Sheath of Light
7232  if (dummySpell->SpellIconID == 3030)
7233  {
7234  // 4 healing tick
7235  basepoints0 = triggerAmount * damage / 400;
7236  triggered_spell_id = 54203;
7237  break;
7238  }
7239  switch (dummySpell->Id)
7240  {
7241  // Judgement of Light
7242  case 20185:
7243  {
7244  if (!victim || !victim->IsAlive() || victim->HasSpellCooldown(20267))
7245  return false;
7246  // 2% of base mana
7247  basepoints0 = int32(victim->CountPctFromMaxHealth(2));
7248  victim->CastCustomSpell(victim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura);
7249  victim->AddSpellCooldown(20267, 0, 4 * IN_MILLISECONDS);
7250  return true;
7251  }
7252  // Judgement of Wisdom
7253  case 20186:
7254  {
7255  if (!victim || !victim->IsAlive() || victim->getPowerType() != POWER_MANA || victim->HasSpellCooldown(20268))
7256  return false;
7257 
7258  // 2% of base mana
7259  basepoints0 = int32(CalculatePct(victim->GetCreateMana(), 2));
7260  victim->CastCustomSpell(victim, 20268, &basepoints0, nullptr, nullptr, true, 0, triggeredByAura);
7261  victim->AddSpellCooldown(20268, 0, 4 * IN_MILLISECONDS);
7262  return true;
7263  }
7264  // Holy Power (Redemption Armor set)
7265  case 28789:
7266  {
7267  if (!victim)
7268  return false;
7269 
7270  // Set class defined buff
7271  switch (victim->getClass())
7272  {
7273  case CLASS_PALADIN:
7274  case CLASS_PRIEST:
7275  case CLASS_SHAMAN:
7276  case CLASS_DRUID:
7277  triggered_spell_id = 28795; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
7278  break;
7279  case CLASS_MAGE:
7280  case CLASS_WARLOCK:
7281  triggered_spell_id = 28793; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
7282  break;
7283  case CLASS_HUNTER:
7284  case CLASS_ROGUE:
7285  triggered_spell_id = 28791; // Increases the friendly target's attack power by $s1 for $d.
7286  break;
7287  case CLASS_WARRIOR:
7288  triggered_spell_id = 28790; // Increases the friendly target's armor
7289  break;
7290  default:
7291  return false;
7292  }
7293  break;
7294  }
7295  // Seal of Vengeance (damage calc on apply aura)
7296  case 31801:
7297  {
7298  if (effIndex != 0 || !victim) // effect 1, 2 used by seal unleashing code
7299  return false;
7300 
7301  // At melee attack or Hammer of the Righteous spell damage considered as melee attack
7302  bool stacker = !procSpell || procSpell->Id == 53595;
7303  // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
7304  bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
7305 
7306  if (!stacker && !damager)
7307  return false;
7308 
7309  triggered_spell_id = 31803;
7310 
7311  // On target with 5 stacks of Holy Vengeance direct damage is done
7312  if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
7313  {
7314  if (aur->GetStackAmount() == 5)
7315  {
7316  if (stacker)
7317  aur->RefreshDuration();
7318 
7319  CastSpell(victim, 42463, true, castItem, triggeredByAura);
7320  return true;
7321  }
7322  }
7323 
7324  if (!stacker)
7325  return false;
7326  break;
7327  }
7328  // Seal of Corruption
7329  case 53736:
7330  {
7331  if (effIndex != 0 || !victim) // effect 1, 2 used by seal unleashing code
7332  return false;
7333 
7334  // At melee attack or Hammer of the Righteous spell damage considered as melee attack
7335  bool stacker = !procSpell || procSpell->Id == 53595;
7336  // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
7337  bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
7338 
7339  if (!stacker && !damager)
7340  return false;
7341 
7342  triggered_spell_id = 53742;
7343 
7344  // On target with 5 stacks of Blood Corruption direct damage is done
7345  if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
7346  {
7347  if (aur->GetStackAmount() == 5)
7348  {
7349  if (stacker)
7350  aur->RefreshDuration();
7351 
7352  CastSpell(victim, 53739, true, castItem, triggeredByAura);
7353  return true;
7354  }
7355  }
7356 
7357  if (!stacker)
7358  return false;
7359  break;
7360  }
7361  // Spiritual Attunement
7362  case 31785:
7363  case 33776:
7364  {
7365  // if healed by another unit (victim)
7366  if (this == victim)
7367  return false;
7368 
7369  // dont allow non-positive dots to proc
7370  if (!procSpell || !procSpell->IsPositive())
7371  return false;
7372 
7373  // heal amount
7374  basepoints0 = int32(CalculatePct(std::min(damage, GetMaxHealth() - GetHealth()), triggerAmount));
7375  target = this;
7376 
7377  if (basepoints0)
7378  triggered_spell_id = 31786;
7379  break;
7380  }
7381  // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
7382  case 40470:
7383  {
7384  if (!procSpell)
7385  return false;
7386 
7387  float chance = 0.0f;
7388 
7389  // Flash of light/Holy light
7390  if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
7391  {
7392  triggered_spell_id = 40471;
7393  chance = 15.0f;
7394  }
7395  // Judgement (any)
7396  else if (procSpell->SpellFamilyFlags[0] & 0x800000)
7397  {
7398  triggered_spell_id = 40472;
7399  chance = 50.0f;
7400  }
7401  else
7402  return false;
7403 
7404  if (!roll_chance_f(chance))
7405  return false;
7406 
7407  break;
7408  }
7409  // Glyph of Holy Light
7410  case 54937:
7411  {
7412  triggered_spell_id = 54968;
7413  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7414  break;
7415  }
7416  // Item - Paladin T8 Holy 2P Bonus
7417  case 64890:
7418  {
7419  triggered_spell_id = 64891;
7420  basepoints0 = triggerAmount * damage / 300;
7421  break;
7422  }
7423  case 71406: // Tiny Abomination in a Jar
7424  case 71545: // Tiny Abomination in a Jar (Heroic)
7425  {
7426  if (!victim || !victim->IsAlive())
7427  return false;
7428 
7429  CastSpell(this, 71432, true, nullptr, triggeredByAura);
7430 
7431  Aura const* dummy = GetAura(71432);
7432  if (!dummy || dummy->GetStackAmount() < (dummySpell->Id == 71406 ? 8 : 7))
7433  return false;
7434 
7435  RemoveAurasDueToSpell(71432);
7436  triggered_spell_id = 71433; // default main hand attack
7437  // roll if offhand
7438  if (Player const* player = ToPlayer())
7439  if (player->GetWeaponForAttack(OFF_ATTACK, true) && urand(0, 1))
7440  triggered_spell_id = 71434;
7441  target = victim;
7442  break;
7443  }
7444  // Item - Icecrown 25 Normal Dagger Proc
7445  case 71880:
7446  {
7447  switch (getPowerType())
7448  {
7449  case POWER_MANA:
7450  triggered_spell_id = 71881;
7451  break;
7452  case POWER_RAGE:
7453  triggered_spell_id = 71883;
7454  break;
7455  case POWER_ENERGY:
7456  triggered_spell_id = 71882;
7457  break;
7458  case POWER_RUNIC_POWER:
7459  triggered_spell_id = 71884;
7460  break;
7461  default:
7462  return false;
7463  }
7464  break;
7465  }
7466  // Item - Icecrown 25 Heroic Dagger Proc
7467  case 71892:
7468  {
7469  switch (getPowerType())
7470  {
7471  case POWER_MANA:
7472  triggered_spell_id = 71888;
7473  break;
7474  case POWER_RAGE:
7475  triggered_spell_id = 71886;
7476  break;
7477  case POWER_ENERGY:
7478  triggered_spell_id = 71887;
7479  break;
7480  case POWER_RUNIC_POWER:
7481  triggered_spell_id = 71885;
7482  break;
7483  default:
7484  return false;
7485  }
7486  break;
7487  }
7488  }
7489  break;
7490  }
7491  case SPELLFAMILY_SHAMAN:
7492  {
7493  switch (dummySpell->Id)
7494  {
7495  // Tidal Force
7496  case 55198:
7497  {
7498  // Remove aura stack from caster
7499  RemoveAuraFromStack(55166);
7500  // drop charges
7501  return false;
7502  }
7503  // Totemic Power (The Earthshatterer set)
7504  case 28823:
7505  {
7506  if (!victim)
7507  return false;
7508 
7509  // Set class defined buff
7510  switch (victim->getClass())
7511  {
7512  case CLASS_PALADIN:
7513  case CLASS_PRIEST:
7514  case CLASS_SHAMAN:
7515  case CLASS_DRUID:
7516  triggered_spell_id = 28824; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
7517  break;
7518  case CLASS_MAGE:
7519  case CLASS_WARLOCK:
7520  triggered_spell_id = 28825; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
7521  break;
7522  case CLASS_HUNTER:
7523  case CLASS_ROGUE:
7524  triggered_spell_id = 28826; // Increases the friendly target's attack power by $s1 for $d.
7525  break;
7526  case CLASS_WARRIOR:
7527  triggered_spell_id = 28827; // Increases the friendly target's armor
7528  break;
7529  default:
7530  return false;
7531  }
7532  break;
7533  }
7534  // Lesser Healing Wave (Totem of Flowing Water Relic)
7535  case 28849:
7536  {
7537  target = this;
7538  triggered_spell_id = 28850;
7539  break;
7540  }
7541  // Windfury Weapon (Passive) 1-8 Ranks
7542  case 33757:
7543  {
7544  Player* player = ToPlayer();
7545  if (!player || !castItem || !castItem->IsEquipped() || !victim || !victim->IsAlive())
7546  return false;
7547 
7548  if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID())
7549  return false;
7550 
7551  WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot()));
7552  if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
7553  || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
7554  || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
7555  return false;
7556 
7557  // Now amount of extra power stored in 1 effect of Enchant spell
7558  // Get it by item enchant id
7559  uint32 spellId;
7561  {
7562  case 283:
7563  spellId = 8232;
7564  break; // 1 Rank
7565  case 284:
7566  spellId = 8235;
7567  break; // 2 Rank
7568  case 525:
7569  spellId = 10486;
7570  break; // 3 Rank
7571  case 1669:
7572  spellId = 16362;
7573  break; // 4 Rank
7574  case 2636:
7575  spellId = 25505;
7576  break; // 5 Rank
7577  case 3785:
7578  spellId = 58801;
7579  break; // 6 Rank
7580  case 3786:
7581  spellId = 58803;
7582  break; // 7 Rank
7583  case 3787:
7584  spellId = 58804;
7585  break; // 8 Rank
7586  default:
7587  {
7588  LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
7589  castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)), dummySpell->Id);
7590  return false;
7591  }
7592  }
7593 
7594  SpellInfo const* windfurySpellInfo = sSpellMgr->GetSpellInfo(spellId);
7595  if (!windfurySpellInfo)
7596  {
7597  LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non-existing spell id: %u (Windfury)", spellId);
7598  return false;
7599  }
7600 
7601  int32 extra_attack_power = CalculateSpellDamage(victim, windfurySpellInfo, 1);
7602 
7603  // Value gained from additional AP
7604  basepoints0 = int32(extra_attack_power / 14.0f * GetAttackTime(attType) / 1000);
7605 
7606  if (procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
7607  triggered_spell_id = 25504;
7608 
7609  if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
7610  triggered_spell_id = 33750;
7611 
7612  // custom cooldown processing case
7613  if (player->HasSpellCooldown(dummySpell->Id))
7614  return false;
7615 
7616  // apply cooldown before cast to prevent processing itself
7617  player->AddSpellCooldown(dummySpell->Id, 0, 3 * IN_MILLISECONDS);
7618 
7619  // Attack Twice
7620  for (uint32 i = 0; i < 2; ++i)
7621  CastCustomSpell(victim, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura);
7622 
7623  return true;
7624  }
7625  // Shaman Tier 6 Trinket
7626  case 40463:
7627  {
7628  if (!procSpell)
7629  return false;
7630 
7631  float chance;
7632  if (procSpell->SpellFamilyFlags[0] & 0x1)
7633  {
7634  triggered_spell_id = 40465; // Lightning Bolt
7635  chance = 15.0f;
7636  }
7637  else if (procSpell->SpellFamilyFlags[0] & 0x80)
7638  {
7639  triggered_spell_id = 40465; // Lesser Healing Wave
7640  chance = 10.0f;
7641  }
7642  else if (procSpell->SpellFamilyFlags[1] & 0x00000010)
7643  {
7644  triggered_spell_id = 40466; // Stormstrike
7645  chance = 50.0f;
7646  }
7647  else
7648  return false;
7649 
7650  if (!roll_chance_f(chance))
7651  return false;
7652 
7653  target = this;
7654  break;
7655  }
7656  // Glyph of Healing Wave
7657  case 55440:
7658  {
7659  // Not proc from self heals
7660  if (this == victim)
7661  return false;
7662  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7663  target = this;
7664  triggered_spell_id = 55533;
7665  break;
7666  }
7667  // Spirit Hunt
7668  case 58877:
7669  {
7670  // Cast on owner
7671  target = GetOwner();
7672  if (!target)
7673  return false;
7674  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7675  triggered_spell_id = 58879;
7676  // Heal wolf
7677  CastCustomSpell(this, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura, originalCaster);
7678  break;
7679  }
7680  // Shaman T8 Elemental 4P Bonus
7681  case 64928:
7682  {
7683  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7684  triggered_spell_id = 64930; // Electrified
7685  break;
7686  }
7687  // Shaman T9 Elemental 4P Bonus
7688  case 67228:
7689  {
7690  // Lava Burst
7691  if (procSpell->SpellFamilyFlags[1] & 0x1000)
7692  {
7693  triggered_spell_id = 71824;
7694  SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
7695  if (!triggeredSpell)
7696  return false;
7697  basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].Amplitude);
7698  }
7699  break;
7700  }
7701  // Item - Shaman T10 Elemental 4P Bonus
7702  case 70817:
7703  {
7704  if (!target)
7705  return false;
7706  // try to find spell Flame Shock on the target
7707  if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0x0, 0x0, GetGUID()))
7708  {
7709  Aura* flameShock = aurEff->GetBase();
7710  int32 maxDuration = flameShock->GetMaxDuration();
7711  int32 newDuration = flameShock->GetDuration() + 2 * aurEff->GetAmplitude();
7712 
7713  flameShock->SetDuration(newDuration);
7714  // is it blizzlike to change max duration for FS?
7715  if (newDuration > maxDuration)
7716  flameShock->SetMaxDuration(newDuration);
7717 
7718  return true;
7719  }
7720  // if not found Flame Shock
7721  return false;
7722  }
7723  break;
7724  }
7725  // Frozen Power
7726  if (dummySpell->SpellIconID == 3780)
7727  {
7728  if (!target)
7729  return false;
7730  if (GetDistance(target) < 15.0f)
7731  return false;
7732  float chance = (float)triggerAmount;
7733  if (!roll_chance_f(chance))
7734  return false;
7735 
7736  triggered_spell_id = 63685;
7737  break;
7738  }
7739  // Ancestral Awakening
7740  if (dummySpell->SpellIconID == 3065)
7741  {
7742  triggered_spell_id = 52759;
7743  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7744  target = this;
7745  break;
7746  }
7747  // Flametongue Weapon (Passive)
7748  if (dummySpell->SpellFamilyFlags[0] & 0x200000)
7749  {
7750  if (GetTypeId() != TYPEID_PLAYER || !victim || !victim->IsAlive() || !castItem || !castItem->IsEquipped())
7751  return false;
7752 
7754  if ((attType != BASE_ATTACK && attType != OFF_ATTACK)
7755  || (attType == BASE_ATTACK && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
7756  || (attType == OFF_ATTACK && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK))
7757  return false;
7758 
7759  float fire_onhit = float(CalculatePct(dummySpell->Effects[EFFECT_0]. CalcValue(), 1.0f));
7760 
7761  float add_spellpower = (float)(SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE)
7763 
7764  // 1.3speed = 5%, 2.6speed = 10%, 4.0 speed = 15%, so, 1.0speed = 3.84%
7765  ApplyPct(add_spellpower, 3.84f);
7766 
7767  // Enchant on Off-Hand and ready?
7768  if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
7769  {
7770  float BaseWeaponSpeed = GetAttackTime(OFF_ATTACK) / 1000.0f;
7771 
7772  // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
7773  basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
7774  triggered_spell_id = 10444;
7775  }
7776 
7777  // Enchant on Main-Hand and ready?
7778  else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
7779  {
7780  float BaseWeaponSpeed = GetAttackTime(BASE_ATTACK) / 1000.0f;
7781 
7782  // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
7783  basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
7784  triggered_spell_id = 10444;
7785  }
7786 
7787  // If not ready, we should return, shouldn't we?!
7788  else
7789  return false;
7790 
7791  CastCustomSpell(victim, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura);
7792  return true;
7793  }
7794  // Improved Water Shield
7795  if (dummySpell->SpellIconID == 2287)
7796  {
7797  if (!procSpell)
7798  return false;
7799 
7800  // Default chance for Healing Wave and Riptide
7801  float chance = (float)triggeredByAura->GetAmount();
7802 
7803  if (procSpell->SpellFamilyFlags[0] & 0x80)
7804  // Lesser Healing Wave - 0.6 of default
7805  chance *= 0.6f;
7806  else if (procSpell->SpellFamilyFlags[0] & 0x100)
7807  // Chain heal - 0.3 of default
7808  chance *= 0.3f;
7809 
7810  if (!roll_chance_f(chance))
7811  return false;
7812 
7813  // Water Shield
7814  if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020, 0))
7815  {
7816  uint32 spell = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
7817  CastSpell(this, spell, true, castItem, triggeredByAura);
7818  return true;
7819  }
7820  return false;
7821  }
7822  // Lightning Overload
7823  if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura
7824  {
7825  if(!procSpell || GetTypeId() != TYPEID_PLAYER || !victim)
7826  return false;
7827 
7828  if (procEx & PROC_EX_CRITICAL_HIT)
7829  damage /= 2;
7830 
7831  do
7832  {
7833  uint32 spell = 0;
7834 
7835  if (procSpell->SpellFamilyFlags[0] & 0x2)
7836  {
7837  // 1/3 of 33% if 11%
7838  if (!roll_chance_i(33))
7839  return false;
7840 
7841  spell = 45297;
7842  }
7843  else
7844  spell = 45284;
7845 
7846  // do not reduce damage-spells have correct basepoints
7847  damage /= 2;
7848  int32 dmg = damage;
7849 
7850  // Cast
7851  CastCustomSpell(victim, spell, &dmg, 0, 0, true, castItem, triggeredByAura);
7852  } while (roll_chance_i(33));
7853  return true;
7854  }
7855  // Static Shock
7856  if (dummySpell->SpellIconID == 3059)
7857  {
7858  // Lightning Shield
7859  if (AuraEffect const* aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0))
7860  {
7861  uint32 spell = sSpellMgr->GetSpellWithRank(26364, aurEff->GetSpellInfo()->GetRank());
7862  CastSpell(target, spell, true, castItem, triggeredByAura);
7863  aurEff->GetBase()->DropCharge();
7864  return true;
7865  }
7866  return false;
7867  }
7868  break;
7869  }
7871  {
7872  // Improved Blood Presence
7873  if (dummySpell->SpellIconID == 2636)
7874  {
7875  if (GetTypeId() != TYPEID_PLAYER)
7876  return false;
7877  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7878  break;
7879  }
7880  // Butchery
7881  if (dummySpell->SpellIconID == 2664)
7882  {
7883  basepoints0 = triggerAmount;
7884  triggered_spell_id = 50163;
7885  target = this;
7886  break;
7887  }
7888  // Mark of Blood
7889  if (dummySpell->Id == 49005)
7890  {
7891  // TODO: need more info (cooldowns/PPM)
7892  triggered_spell_id = 61607;
7893  break;
7894  }
7895  // Unholy Blight
7896  if (dummySpell->Id == 49194)
7897  {
7898  triggered_spell_id = 50536;
7899  SpellInfo const* unholyBlight = sSpellMgr->GetSpellInfo(triggered_spell_id);
7900  if (!unholyBlight || !victim)
7901  return false;
7902 
7903  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7904 
7905  //Glyph of Unholy Blight
7906  if (AuraEffect* glyph = GetAuraEffect(63332, 0))
7907  AddPct(basepoints0, glyph->GetAmount());
7908 
7909  basepoints0 = basepoints0 / (unholyBlight->GetMaxDuration() / unholyBlight->Effects[0].Amplitude);
7910  victim->CastDelayedSpellWithPeriodicAmount(this, triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE, basepoints0);
7911  return true;
7912  }
7913  // Vendetta
7914  if (dummySpell->SpellFamilyFlags[0] & 0x10000)
7915  {
7916  basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
7917  triggered_spell_id = 50181;
7918  target = this;
7919  break;
7920  }
7921  // Necrosis
7922  if (dummySpell->SpellIconID == 2709)
7923  {
7924  basepoints0 = CalculatePct(int32(damage), triggerAmount);
7925  triggered_spell_id = 51460;
7926  break;
7927  }
7928  // Threat of Thassarian
7929  if (dummySpell->SpellIconID == 2023)
7930  {
7931  // Must Dual Wield
7932  if (!procSpell || !haveOffhandWeapon())
7933  return false;
7934  // Chance as basepoints for dummy aura
7935  if (!roll_chance_i(triggerAmount))
7936  return false;
7937 
7938  switch (procSpell->Id)
7939  {
7940  // Obliterate
7941  case 49020:
7942  triggered_spell_id = 66198;
7943  break; // Rank 1
7944  case 51423:
7945  triggered_spell_id = 66972;
7946  break; // Rank 2
7947  case 51424:
7948  triggered_spell_id = 66973;
7949  break; // Rank 3
7950  case 51425:
7951  triggered_spell_id = 66974;
7952  break; // Rank 4
7953 
7954  // Frost Strike
7955  case 49143:
7956  triggered_spell_id = 66196;
7957  break; // Rank 1
7958  case 51416:
7959  triggered_spell_id = 66958;
7960  break; // Rank 2
7961  case 51417:
7962  triggered_spell_id = 66959;
7963  break; // Rank 3
7964  case 51418:
7965  triggered_spell_id = 66960;
7966  break; // Rank 4
7967  case 51419:
7968  triggered_spell_id = 66961;
7969  break; // Rank 5
7970  case 55268:
7971  triggered_spell_id = 66962;
7972  break; // Rank 6
7973 
7974  // Plague Strike
7975  case 45462:
7976  triggered_spell_id = 66216;
7977  break; // Rank 1
7978  case 49917:
7979  triggered_spell_id = 66988;
7980  break; // Rank 2
7981  case 49918:
7982  triggered_spell_id = 66989;
7983  break; // Rank 3
7984  case 49919:
7985  triggered_spell_id = 66990;
7986  break; // Rank 4
7987  case 49920:
7988  triggered_spell_id = 66991;
7989  break; // Rank 5
7990  case 49921:
7991  triggered_spell_id = 66992;
7992  break; // Rank 6
7993 
7994  // Death Strike
7995  case 49998:
7996  triggered_spell_id = 66188;
7997  break; // Rank 1
7998  case 49999:
7999  triggered_spell_id = 66950;
8000  break; // Rank 2
8001  case 45463:
8002  triggered_spell_id = 66951;
8003  break; // Rank 3
8004  case 49923:
8005  triggered_spell_id = 66952;
8006  break; // Rank 4
8007  case 49924:
8008  triggered_spell_id = 66953;
8009  break; // Rank 5
8010 
8011  // Rune Strike
8012  case 56815:
8013  triggered_spell_id = 66217;
8014  break; // Rank 1
8015 
8016  // Blood Strike
8017  case 45902:
8018  triggered_spell_id = 66215;
8019  break; // Rank 1
8020  case 49926:
8021  triggered_spell_id = 66975;
8022  break; // Rank 2
8023  case 49927:
8024  triggered_spell_id = 66976;
8025  break; // Rank 3
8026  case 49928:
8027  triggered_spell_id = 66977;
8028  break; // Rank 4
8029  case 49929:
8030  triggered_spell_id = 66978;
8031  break; // Rank 5
8032  case 49930:
8033  triggered_spell_id = 66979;
8034  break; // Rank 6
8035  default:
8036  return false;
8037  }
8038 
8039  // This should do, restore spell mod so next attack can also use this!
8040  // crit chance for first strike is already computed
8041  ToPlayer()->RestoreSpellMods(m_currentSpells[CURRENT_GENERIC_SPELL], 51124, nullptr); // Killing Machine
8042  ToPlayer()->RestoreSpellMods(m_currentSpells[CURRENT_GENERIC_SPELL], 49796, nullptr); // Deathchill
8043 
8044  // Xinef: Somehow basepoints are divided by 2 which is later divided by 2 (offhand multiplier)
8045  SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
8046  if (triggerEntry->SchoolMask & SPELL_SCHOOL_MASK_NORMAL)
8047  basepoints0 = triggerEntry->Effects[EFFECT_0].BasePoints * 2;
8048 
8049  SetCantProc(true);
8050  if(basepoints0)
8051  CastCustomSpell(target, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura, originalCaster);
8052  else
8053  CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
8054  SetCantProc(false);
8055  return true;
8056  }
8057  // Runic Power Back on Snare/Root
8058  if (dummySpell->Id == 61257)
8059  {
8060  // only for spells and hit/crit (trigger start always) and not start from self casted spells
8061  if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) || this == victim)
8062  return false;
8063  // Need snare or root mechanic
8064  if (!(procSpell->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_SNARE))))
8065  return false;
8066  triggered_spell_id = 61258;
8067  target = this;
8068  break;
8069  }
8070  // Sudden Doom
8071  if (dummySpell->SpellIconID == 1939 && GetTypeId() == TYPEID_PLAYER)
8072  {
8073  SpellChainNode const* chain = nullptr;
8074  // get highest rank of the Death Coil spell
8075  PlayerSpellMap const& sp_list = ToPlayer()->GetSpellMap();
8076  for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
8077  {
8078  // check if shown in spell book
8079  if (!itr->second->Active || !itr->second->IsInSpec(ToPlayer()->GetActiveSpec()) || itr->second->State == PLAYERSPELL_REMOVED)
8080  continue;
8081 
8082  SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(itr->first);
8083  if (!spellProto)
8084  continue;
8085 
8086  if (spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT
8087  && spellProto->SpellFamilyFlags[0] & 0x2000)
8088  {
8089  SpellChainNode const* newChain = sSpellMgr->GetSpellChainNode(itr->first);
8090 
8091  // No chain entry or entry lower than found entry
8092  if (!chain || !newChain || (chain->rank < newChain->rank))
8093  {
8094  triggered_spell_id = itr->first;
8095  chain = newChain;
8096  }
8097  else
8098  continue;
8099  // Found spell is last in chain - do not need to look more
8100  // Optimisation for most common case
8101  if (chain && chain->last->Id == itr->first)
8102  break;
8103  }
8104  }
8105  }
8106  break;
8107  }
8108  case SPELLFAMILY_POTION:
8109  {
8110  // alchemist's stone
8111  if (dummySpell->Id == 17619)
8112  {
8113  if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
8114  {
8115  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
8116  {
8117  if (procSpell->Effects[i].Effect == SPELL_EFFECT_HEAL)
8118  {
8119  triggered_spell_id = 21399;
8120  }
8121  else if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
8122  {
8123  triggered_spell_id = 21400;
8124  }
8125  else
8126  continue;
8127 
8128  basepoints0 = int32(CalculateSpellDamage(this, procSpell, i) * 0.4f);
8129  CastCustomSpell(this, triggered_spell_id, &basepoints0, nullptr, nullptr, true, nullptr, triggeredByAura);
8130  }
8131  return true;
8132  }
8133  }
8134  break;
8135  }
8136  case SPELLFAMILY_PET:
8137  {
8138  switch (dummySpell->SpellIconID)
8139  {
8140  // Guard Dog
8141  case 201:
8142  {
8143  if (!victim)
8144  return false;
8145 
8146  triggered_spell_id = 54445;
8147  target = this;
8148  float addThreat = float(CalculatePct(procSpell->Effects[0].CalcValue(this), triggerAmount));
8149  victim->AddThreat(this, addThreat);
8150  break;
8151  }
8152  // Silverback
8153  case 1582:
8154  triggered_spell_id = dummySpell->Id == 62765 ? 62801 : 62800;
8155  target = this;
8156  break;
8157  }
8158  break;
8159  }
8160  default:
8161  break;
8162  }
8163 
8164  // if not handled by custom case, get triggered spell from dummySpell proto
8165  if (!triggered_spell_id)
8166  triggered_spell_id = dummySpell->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
8167 
8168  // processed charge only counting case
8169  if (!triggered_spell_id)
8170  return true;
8171 
8172  SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
8173  if (!triggerEntry)
8174  {
8175  LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: Spell %u has non-existing triggered spell %u", dummySpell->Id, triggered_spell_id);
8176  return false;
8177  }
8178 
8179  if (cooldown_spell_id == 0)
8180  cooldown_spell_id = triggered_spell_id;
8181 
8182  if (cooldown)
8183  {
8184  if (HasSpellCooldown(cooldown_spell_id))
8185  return false;
8186 
8187  AddSpellCooldown(cooldown_spell_id, 0, cooldown);
8188  }
8189 
8190  if(basepoints0)
8191  CastCustomSpell(target, triggered_spell_id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura, originalCaster);
8192  else
8193  CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
8194 
8195  return true;
8196 }
8197 
8198 // Used in case when access to whole aura is needed
8199 // All procs should be handled like this...
8200 bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 /*procFlag*/, uint32 procEx, uint32 /*cooldown*/, bool* handled)
8201 {
8202  SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
8203 
8204  switch (dummySpell->SpellFamilyName)
8205  {
8206  case SPELLFAMILY_GENERIC:
8207  switch (dummySpell->Id)
8208  {
8209  // Nevermelting Ice Crystal
8210  case 71564:
8211  RemoveAuraFromStack(71564);
8212  *handled = true;
8213  break;
8214  // Gaseous Bloat
8215  case 70672:
8216  case 72455:
8217  case 72832:
8218  case 72833:
8219  {
8220  if (Unit* caster = triggeredByAura->GetCaster())
8221  if (victim && caster->GetGUID() == victim->GetGUID())
8222  {
8223  *handled = true;
8224  uint32 stack = triggeredByAura->GetStackAmount();
8225  int32 const mod = (GetMap()->GetSpawnMode() & 1) ? 1500 : 1250;
8226  int32 dmg = 0;
8227  for (uint8 i = 1; i <= stack; ++i)
8228  dmg += mod * i;
8229  caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
8230  }
8231  break;
8232  }
8233  // Ball of Flames Proc
8234  case 71756:
8235  case 72782:
8236  case 72783:
8237  case 72784:
8238  RemoveAuraFromStack(dummySpell->Id);
8239  *handled = true;
8240  break;
8241  // Discerning Eye of the Beast
8242  case 59915:
8243  {
8244  CastSpell(this, 59914, true); // 59914 already has correct basepoints in DBC, no need for custom bp
8245  *handled = true;
8246  break;
8247  }
8248  // Swift Hand of Justice
8249  case 59906:
8250  {
8251  int32 bp0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_0]. CalcValue());
8252  CastCustomSpell(this, 59913, &bp0, nullptr, nullptr, true);
8253  *handled = true;
8254  break;
8255  }
8256  }
8257 
8258  break;
8259  case SPELLFAMILY_MAGE:
8260  {
8261  // Combustion
8262  switch (dummySpell->Id)
8263  {
8264  case 11129:
8265  {
8266  *handled = true;
8267  Unit* caster = triggeredByAura->GetCaster();
8268  if (!caster || !damage)
8269  return false;
8270 
8271  // last charge and crit
8272  if (triggeredByAura->GetCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT))
8273  return true; // charge counting (will removed)
8274 
8275  CastSpell(this, 28682, true);
8276 
8277  return procEx & PROC_EX_CRITICAL_HIT;
8278  }
8279  // Empowered Fire
8280  case 31656:
8281  case 31657:
8282  case 31658:
8283  {
8284  *handled = true;
8285 
8286  SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(67545);
8287  if (!spInfo)
8288  return false;
8289 
8290  int32 bp0 = int32(CalculatePct(GetMaxPower(POWER_MANA), spInfo->Effects[0].CalcValue()));
8291  CastCustomSpell(this, 67545, &bp0, nullptr, nullptr, true, nullptr, triggeredByAura->GetEffect(EFFECT_0), GetGUID());
8292  return true;
8293  }
8294  }
8295  break;
8296  }
8298  {
8299  // Blood of the North
8300  // Reaping
8301  // Death Rune Mastery
8302  // xinef: Icon 22 is used for item bonus, skip
8303  if (dummySpell->SpellIconID == 3041 || (dummySpell->SpellIconID == 22 && dummySpell->Id != 62459) || dummySpell->SpellIconID == 2622)
8304  {
8305  *handled = true;
8306  // Convert recently used Blood Rune to Death Rune
8307  if (Player* player = ToPlayer())
8308  {
8309  if (player->getClass() != CLASS_DEATH_KNIGHT)
8310  return false;
8311 
8312  // xinef: not true
8313  //RuneType rune = ToPlayer()->GetLastUsedRune();
8314  // can't proc from death rune use
8315  //if (rune == RUNE_DEATH)
8316  // return false;
8317  AuraEffect* aurEff = triggeredByAura->GetEffect(EFFECT_0);
8318  if (!aurEff)
8319  return false;
8320 
8321  // Reset amplitude - set death rune remove timer to 30s
8322  aurEff->ResetPeriodic(true);
8323  uint32 runesLeft;
8324 
8325  if (dummySpell->SpellIconID == 2622)
8326  runesLeft = 2;
8327  else
8328  runesLeft = 1;
8329 
8330  for (uint8 i = 0; i < MAX_RUNES && runesLeft; ++i)
8331  {
8332  if (dummySpell->SpellIconID == 2622)
8333  {
8334  if (player->GetCurrentRune(i) == RUNE_DEATH ||
8335  player->GetBaseRune(i) == RUNE_BLOOD)
8336  continue;
8337  }
8338  else
8339  {
8340  if (player->GetCurrentRune(i) == RUNE_DEATH ||
8341  player->GetBaseRune(i) != RUNE_BLOOD)
8342  continue;
8343  }
8344  if (player->GetRuneCooldown(i) != player->GetRuneBaseCooldown(i, false))
8345  continue;
8346 
8347  --runesLeft;
8348  // Mark aura as used
8349  player->AddRuneByAuraEffect(i, RUNE_DEATH, aurEff);
8350  }
8351  return true;
8352  }
8353  return false;
8354  }
8355  break;
8356  }
8357  case SPELLFAMILY_WARRIOR:
8358  {
8359  switch (dummySpell->Id)
8360  {
8361  // Item - Warrior T10 Protection 4P Bonus
8362  case 70844:
8363  {
8364  int32 basepoints0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_1]. CalcValue());
8365  CastCustomSpell(this, 70845, &basepoints0, nullptr, nullptr, true);
8366  break;
8367  }
8368  default:
8369  break;
8370  }
8371  break;
8372  }
8373  }
8374  return false;
8375 }
8376 
8377 bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown)
8378 {
8379  // Get triggered aura spell info
8380  SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
8381 
8382  // Basepoints of trigger aura
8383  int32 triggerAmount = triggeredByAura->GetAmount();
8384 
8385  // Set trigger spell id, target, custom basepoints
8386  uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
8387 
8388  Unit* target = nullptr;
8389  int32 basepoints0 = 0;
8390 
8391  if (triggeredByAura->GetAuraType() == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
8392  basepoints0 = triggerAmount;
8393 
8394  Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
8395  ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : nullptr;
8396 
8397  // Try handle unknown trigger spells
8398  //if (sSpellMgr->GetSpellInfo(trigger_spell_id) == nullptr)
8399  {
8400  switch (auraSpellInfo->SpellFamilyName)
8401  {
8402  case SPELLFAMILY_GENERIC:
8403  switch (auraSpellInfo->Id)
8404  {
8405  case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
8406  // Pct value stored in dummy
8407  if (!victim)
8408  return false;
8409  basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100;
8410  target = victim;
8411  break;
8412  case 57345: // Darkmoon Card: Greatness
8413  {
8414  float stat = 0.0f;
8415  // strength
8416  if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229; stat = GetStat(STAT_STRENGTH); }
8417  // agility
8418  if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 60233; stat = GetStat(STAT_AGILITY); }
8419  // intellect
8420  if (GetStat(STAT_INTELLECT) > stat) { trigger_spell_id = 60234; stat = GetStat(STAT_INTELLECT);}
8421  // spirit
8422  if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235; }
8423  break;
8424  }
8425  case 67702: // Death's Choice, Item - Coliseum 25 Normal Melee Trinket
8426  {
8427  if (!damage)
8428  return false;
8429  float stat = 0.0f;
8430  // strength
8431  if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67708; stat = GetStat(STAT_STRENGTH); }
8432  // agility
8433  if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67703; }
8434  break;
8435  }
8436  case 67771: // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket
8437  {
8438  if (!damage)
8439  return false;
8440  float stat = 0.0f;
8441  // strength
8442  if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67773; stat = GetStat(STAT_STRENGTH); }
8443  // agility
8444  if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67772; }
8445  break;
8446  }
8447  // Mana Drain Trigger
8448  case 27522:
8449  case 40336:
8450  {
8451  // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target.
8452  if (IsAlive())
8453  CastSpell(this, 29471, true, castItem, triggeredByAura);
8454  if (victim && victim->IsAlive())
8455  CastSpell(victim, 27526, true, castItem, triggeredByAura);
8456  return true;
8457  }
8458  // Forge of Souls, Devourer of Souls, Mirrored Soul
8459  case 69023:
8460  {
8461  int32 dmg = damage * 0.45f;
8462  if (dmg > 0)
8463  if (Aura* a = GetAura(69023))
8464  if (Unit* c = a->GetCaster())
8465  CastCustomSpell(c, 69034, &dmg, 0, 0, true);
8466  return true;
8467  }
8468  // Soul-Trader Beacon proc aura
8469  case 50051:
8470  {
8471  if (!victim)
8472  return false;
8473 
8475  cr->CastSpell(victim, 50101, true);
8476 
8477  return false;
8478  }
8479  }
8480  break;
8481  case SPELLFAMILY_MAGE:
8482  if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed
8483  {
8484  switch (auraSpellInfo->Id)
8485  {
8486  case 31641: // Rank 1
8487  case 31642: // Rank 2
8488  trigger_spell_id = 31643;
8489  break;
8490  default:
8491  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed", auraSpellInfo->Id);
8492  return false;
8493  }
8494  }
8495  break;
8496  case SPELLFAMILY_WARLOCK:
8497  {
8498  // Nether Protection
8499  if (auraSpellInfo->SpellIconID == 1985)
8500  {
8501  if (!procSpell)
8502  return false;
8503  switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
8504  {
8505  case SPELL_SCHOOL_NORMAL:
8506  return false; // ignore
8507  case SPELL_SCHOOL_HOLY:
8508  trigger_spell_id = 54370;
8509  break;
8510  case SPELL_SCHOOL_FIRE:
8511  trigger_spell_id = 54371;
8512  break;
8513  case SPELL_SCHOOL_NATURE:
8514  trigger_spell_id = 54375;
8515  break;
8516  case SPELL_SCHOOL_FROST:
8517  trigger_spell_id = 54372;
8518  break;
8519  case SPELL_SCHOOL_SHADOW:
8520  trigger_spell_id = 54374;
8521  break;
8522  case SPELL_SCHOOL_ARCANE:
8523  trigger_spell_id = 54373;
8524  break;
8525  default:
8526  return false;
8527  }
8528  }
8529  break;
8530  }
8531  case SPELLFAMILY_PRIEST:
8532  {
8533  // Blessed Recovery
8534  if (auraSpellInfo->SpellIconID == 1875)
8535  {
8536  switch (auraSpellInfo->Id)
8537  {
8538  case 27811:
8539  trigger_spell_id = 27813;
8540  break;
8541  case 27815:
8542  trigger_spell_id = 27817;
8543  break;
8544  case 27816:
8545  trigger_spell_id = 27818;
8546  break;
8547  default:
8548  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
8549  return false;
8550  }
8551  basepoints0 = CalculatePct(int32(damage), triggerAmount) / 3;
8552  target = this;
8553  // Add remaining ticks to healing done
8554  CastDelayedSpellWithPeriodicAmount(this, trigger_spell_id, SPELL_AURA_PERIODIC_HEAL, basepoints0);
8555  return true;
8556  }
8557  break;
8558  }
8559  case SPELLFAMILY_DRUID:
8560  {
8561  switch (auraSpellInfo->Id)
8562  {
8563  // Druid Forms Trinket
8564  case 37336:
8565  {
8566  switch (GetShapeshiftForm())
8567  {
8568  case FORM_NONE:
8569  trigger_spell_id = 37344;
8570  break;
8571  case FORM_CAT:
8572  trigger_spell_id = 37341;
8573  break;
8574  case FORM_BEAR:
8575  case FORM_DIREBEAR:
8576  trigger_spell_id = 37340;
8577  break;
8578  case FORM_TREE:
8579  trigger_spell_id = 37342;
8580  break;
8581  case FORM_MOONKIN:
8582  trigger_spell_id = 37343;
8583  break;
8584  default:
8585  return false;
8586  }
8587  break;
8588  }
8589  // Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred)
8590  case 67353:
8591  {
8592  switch (GetShapeshiftForm())
8593  {
8594  case FORM_CAT:
8595  trigger_spell_id = 67355;
8596  break;
8597  case FORM_BEAR:
8598  case FORM_DIREBEAR:
8599  trigger_spell_id = 67354;
8600  break;
8601  default:
8602  return false;
8603  }
8604  break;
8605  }
8606  default:
8607  break;
8608  }
8609  break;
8610  }
8611  case SPELLFAMILY_HUNTER:
8612  {
8613  if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots
8614  {
8615  if (!victim)
8616  return false;
8617 
8618  switch (auraSpellInfo->Id)
8619  {
8620  case 53234: // Rank 1
8621  case 53237: // Rank 2
8622  case 53238: // Rank 3
8623  trigger_spell_id = 63468;
8624  break;
8625  default:
8626  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id);
8627  return false;
8628  }
8629  SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id);
8630  if (!TriggerPS)
8631  return false;
8632 
8633  basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].Amplitude);
8634  victim->CastDelayedSpellWithPeriodicAmount(this, trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE, basepoints0);
8635  return true;
8636  }
8637  // Item - Hunter T9 4P Bonus (Steady Shot)
8638  else if (auraSpellInfo->Id == 67151)
8639  {
8640  if (GetTypeId() != TYPEID_PLAYER || !ToPlayer()->GetPet())
8641  return false;
8642 
8643  target = ToPlayer()->GetPet();
8644  trigger_spell_id = 68130;
8645  break;
8646  }
8647  break;
8648  }
8649  case SPELLFAMILY_PALADIN:
8650  {
8651  switch (auraSpellInfo->Id)
8652  {
8653  // Soul Preserver
8654  case 60510:
8655  {
8656  switch (getClass())
8657  {
8658  case CLASS_DRUID:
8659  trigger_spell_id = 60512;
8660  break;
8661  case CLASS_PALADIN:
8662  trigger_spell_id = 60513;
8663  break;
8664  case CLASS_PRIEST:
8665  trigger_spell_id = 60514;
8666  break;
8667  case CLASS_SHAMAN:
8668  trigger_spell_id = 60515;
8669  break;
8670  }
8671 
8672  target = this;
8673  break;
8674  }
8675  case 37657: // Lightning Capacitor
8676  case 54841: // Thunder Capacitor
8677  case 67712: // Item - Coliseum 25 Normal Caster Trinket
8678  case 67758: // Item - Coliseum 25 Heroic Caster Trinket
8679  {
8680  if (!victim || !victim->IsAlive() || GetTypeId() != TYPEID_PLAYER)
8681  return false;
8682 
8683  uint32 stack_spell_id = 0;
8684  switch (auraSpellInfo->Id)
8685  {
8686  case 37657:
8687  stack_spell_id = 37658;
8688  trigger_spell_id = 37661;
8689  break;
8690  case 54841:
8691  stack_spell_id = 54842;
8692  trigger_spell_id = 54843;
8693  break;
8694  case 67712:
8695  stack_spell_id = 67713;
8696  trigger_spell_id = 67714;
8697  break;
8698  case 67758:
8699  stack_spell_id = 67759;
8700  trigger_spell_id = 67760;
8701  break;
8702  }
8703 
8704  if (cooldown && GetTypeId() == TYPEID_PLAYER)
8705  {
8706  if (ToPlayer()->HasSpellCooldown(stack_spell_id))
8707  return false;
8708 
8709  ToPlayer()->AddSpellCooldown(stack_spell_id, 0, cooldown);
8710  }
8711 
8712  CastSpell(this, stack_spell_id, true, nullptr, triggeredByAura);
8713 
8714  Aura* dummy = GetAura(stack_spell_id);
8715  if (!dummy || dummy->GetStackAmount() < triggerAmount)
8716  return false;
8717 
8718  RemoveAurasDueToSpell(stack_spell_id);
8719  CastSpell(victim, trigger_spell_id, true, nullptr, triggeredByAura);
8720  return true;
8721  }
8722  default:
8723  // Illumination
8724  if (auraSpellInfo->SpellIconID == 241)
8725  {
8726  if (!procSpell)
8727  return false;
8728  // procspell is triggered spell but we need mana cost of original casted spell
8729  uint32 originalSpellId = procSpell->Id;
8730  // Holy Shock heal
8731  if (procSpell->SpellFamilyFlags[1] & 0x00010000)
8732  {
8733  switch (procSpell->Id)
8734  {
8735  case 25914:
8736  originalSpellId = 20473;
8737  break;
8738  case 25913:
8739  originalSpellId = 20929;
8740  break;
8741  case 25903:
8742  originalSpellId = 20930;
8743  break;
8744  case 27175:
8745  originalSpellId = 27174;
8746  break;
8747  case 33074:
8748  originalSpellId = 33072;
8749  break;
8750  case 48820:
8751  originalSpellId = 48824;
8752  break;
8753  case 48821:
8754  originalSpellId = 48825;
8755  break;
8756  default:
8757  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id);
8758  return false;
8759  }
8760  }
8761  SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId);
8762  if (!originalSpell)
8763  {
8764  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu", originalSpellId);
8765  return false;
8766  }
8767  // percent stored in effect 1 (class scripts) base points
8768  int32 cost = int32(originalSpell->ManaCost + CalculatePct(GetCreateMana(), originalSpell->ManaCostPercentage));
8769  basepoints0 = CalculatePct(cost, auraSpellInfo->Effects[1].CalcValue());
8770  trigger_spell_id = 20272;
8771  target = this;
8772  }
8773  break;
8774  }
8775  break;
8776  }
8777  case SPELLFAMILY_SHAMAN:
8778  {
8779  // Lightning Shield (overwrite non existing triggered spell call in spell.dbc
8780  if (auraSpellInfo->SpellFamilyFlags[0] & 0x400)
8781  {
8782  trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank());
8783  }
8784  // Nature's Guardian
8785  else if (auraSpellInfo->SpellIconID == 2013)
8786  {
8787  // Check health condition - should drop to less 30% (damage deal after this!)
8788  if (!HealthBelowPctDamaged(30, damage))
8789  return false;
8790 
8791  if (victim && victim->IsAlive())
8792  victim->getThreatMgr().modifyThreatPercent(this, -10);
8793 
8794  basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
8795  trigger_spell_id = 31616;
8796  target = this;
8797  }
8798  break;
8799  }
8801  {
8802  // Acclimation
8803  if (auraSpellInfo->SpellIconID == 1930)
8804  {
8805  if (!procSpell)
8806  return false;
8807  switch (GetFirstSchoolInMask(procSpell->GetSchoolMask()))
8808  {
8809  case SPELL_SCHOOL_NORMAL:
8810  return false; // ignore
8811  case SPELL_SCHOOL_HOLY:
8812  trigger_spell_id = 50490;
8813  break;
8814  case SPELL_SCHOOL_FIRE:
8815  trigger_spell_id = 50362;
8816  break;
8817  case SPELL_SCHOOL_NATURE:
8818  trigger_spell_id = 50488;
8819  break;
8820  case SPELL_SCHOOL_FROST:
8821  trigger_spell_id = 50485;
8822  break;
8823  case SPELL_SCHOOL_SHADOW:
8824  trigger_spell_id = 50489;
8825  break;
8826  case SPELL_SCHOOL_ARCANE:
8827  trigger_spell_id = 50486;
8828  break;
8829  default:
8830  return false;
8831  }
8832  }
8833  // Blood Presence (Improved)
8834  else if (auraSpellInfo->Id == 63611)
8835  {
8836  if (GetTypeId() != TYPEID_PLAYER)
8837  return false;
8838 
8839  trigger_spell_id = 50475;
8840  basepoints0 = CalculatePct(int32(damage), triggerAmount);
8841  }
8842  break;
8843  }
8844  }
8845  }
8846 
8847  // All ok. Check current trigger spell
8848  SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
8849  if (triggerEntry == nullptr)
8850  {
8851  // Don't cast unknown spell
8852  LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u (effIndex: %u) has unknown TriggerSpell %u. Unhandled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex(), trigger_spell_id);
8853  return false;
8854  }
8855 
8856  // not allow proc extra attack spell at extra attack
8858  return false;
8859 
8860  // Custom requirements (not listed in procEx) Warning! damage dealing after this
8861  // Custom triggered spells
8862  switch (auraSpellInfo->Id)
8863  {
8864  // Deep Wounds
8865  case 12834:
8866  case 12849:
8867  case 12867:
8868  {
8869  if (GetTypeId() != TYPEID_PLAYER)
8870  return false;
8871 
8872  if (procFlags & PROC_FLAG_DONE_OFFHAND_ATTACK)
8874  else
8876  break;
8877  }
8878  // Persistent Shield (Scarab Brooch trinket)
8879  // This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
8880  case 26467:
8881  {
8882  basepoints0 = int32(CalculatePct(damage, 15));
8883  target = victim;
8884  trigger_spell_id = 26470;
8885  break;
8886  }
8887  // Unyielding Knights (item exploit 29108\29109)
8888  case 38164:
8889  {
8890  if (!victim || victim->GetEntry() != 19457) // Proc only if your target is Grillok
8891  return false;
8892  break;
8893  }
8894  // Deflection
8895  case 52420:
8896  {
8897  if (!HealthBelowPct(35))
8898  return false;
8899  break;
8900  }
8901 
8902  // Cheat Death
8903  case 28845:
8904  {
8905  // When your health drops below 20%
8906  if (HealthBelowPctDamaged(20, damage) || HealthBelowPct(20))
8907  return false;
8908  break;
8909  }
8910  // Deadly Swiftness (Rank 1)
8911  case 31255:
8912  {
8913  // whenever you deal damage to a target who is below 20% health.
8914  if (!victim || !victim->IsAlive() || victim->HealthAbovePct(20))
8915  return false;
8916 
8917  target = this;
8918  trigger_spell_id = 22588;
8919  [[fallthrough]]; // TODO: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
8920  }
8921  // Bonus Healing (Crystal Spire of Karabor mace)
8922  case 40971:
8923  {
8924  // If your target is below $s1% health
8925  if (!victim || !victim->IsAlive() || victim->HealthAbovePct(triggerAmount))
8926  return false;
8927  break;
8928  }
8929  // Rapid Recuperation
8930  case 53228:
8931  case 53232:
8932  {
8933  // This effect only from Rapid Fire (ability cast)
8934  if (!(procSpell->SpellFamilyFlags[0] & 0x20))
8935  return false;
8936  break;
8937  }
8938  // Decimation
8939  case 63156:
8940  case 63158:
8941  // Can proc only if target has hp below 35%
8942  if (!victim || !victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, procSpell, this))
8943  return false;
8944  break;
8945  // Ulduar, Hodir, Toasty Fire
8946  case 62821:
8947  if (this->GetTypeId() != TYPEID_PLAYER) // spell has Attribute, but persistent area auras ignore it
8948  return false;
8949  break;
8950  case 15337: // Improved Spirit Tap (Rank 1)
8951  case 15338: // Improved Spirit Tap (Rank 2)
8952  {
8953  if (!procSpell)
8954  return false;
8955 
8956  if (procSpell->SpellFamilyFlags[0] & 0x800000)
8957  if ((procSpell->Id != 58381) || !roll_chance_i(50))
8958  return false;
8959 
8960  target = victim;
8961  break;
8962  }
8963  // Professor Putricide - Ooze Spell Tank Protection
8964  case 71770:
8965  if (victim)
8966  victim->CastSpell(victim, trigger_spell_id, true); // EffectImplicitTarget is self
8967  return true;
8968  case 45057: // Evasive Maneuvers (Commendation of Kael`thas trinket)
8969  case 71634: // Item - Icecrown 25 Normal Tank Trinket 1
8970  case 71640: // Item - Icecrown 25 Heroic Tank Trinket 1
8971  case 75475: // Item - Chamber of Aspects 25 Normal Tank Trinket
8972  case 75481: // Item - Chamber of Aspects 25 Heroic Tank Trinket
8973  {
8974  // Procs only if damage takes health below $s1%
8975  if (!HealthBelowPctDamaged(triggerAmount, damage))
8976  return false;
8977  break;
8978  }
8979  default:
8980  break;
8981  }
8982 
8983  if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
8984  {
8985  // Xinef: keep this order, Aura 70656 has SpellIconID 85!
8986  // Item - Death Knight T10 Melee 4P Bonus
8987  if (auraSpellInfo->Id == 70656)
8988  {
8990  return false;
8991 
8992  for (uint8 i = 0; i < MAX_RUNES; ++i)
8993  if (ToPlayer()->GetRuneCooldown(i) == 0)
8994  return false;
8995  }
8996  // Blade Barrier
8997  else if (auraSpellInfo->SpellIconID == 85)
8998  {
8999  Player* plr = ToPlayer();
9000  if (!plr || plr->getClass() != CLASS_DEATH_KNIGHT || !procSpell)
9001  return false;
9002 
9004  return false;
9005  }
9006  // Rime
9007  else if (auraSpellInfo->SpellIconID == 56)
9008  {
9009  if (GetTypeId() != TYPEID_PLAYER)
9010  return false;
9011 
9012  // Howling Blast
9014  }
9015  }
9016  else if (auraSpellInfo->SpellFamilyName == SPELLFAMILY_DRUID)
9017  {
9018  // Nature's Grasp
9019  if( triggerEntry->SpellIconID == 20 )
9020  {
9021  if (!victim)
9022  return false;
9023 
9024  if (AuraEffect* aurEff = victim->GetAuraEffect(SPELL_AURA_MOD_ROOT, SPELLFAMILY_DRUID, 20, 0))
9025  if ((aurEff->GetBase()->GetMaxDuration() - aurEff->GetBase()->GetDuration()) < 1000)
9026  return false;
9027 
9028  CastSpell(victim, trigger_spell_id, true);
9029  return true;
9030  }
9031  }
9032 
9033  // Custom basepoints/target for exist spell
9034  // dummy basepoints or other customs
9035  switch (trigger_spell_id)
9036  {
9037  // Auras which should proc on area aura source (caster in this case):
9038  // Turn the Tables
9039  case 52914:
9040  case 52915:
9041  case 52910:
9042  // Honor Among Thieves
9043  case 51699:
9044  {
9045  target = triggeredByAura->GetBase()->GetCaster();
9046  if (!target)
9047  return false;
9048 
9049  if (Player* pTarget = target->ToPlayer())
9050  {
9051  if (cooldown)
9052  {
9053  if (pTarget->HasSpellCooldown(trigger_spell_id) )
9054  return false;
9055  pTarget->AddSpellCooldown(trigger_spell_id, 0, cooldown);
9056  }
9057 
9058  Unit* cptarget = nullptr;
9059  if (trigger_spell_id == 51699)
9060  {
9061  cptarget = ObjectAccessor::GetUnit(*target, pTarget->GetComboTarget());
9062  if (!cptarget)
9063  cptarget = pTarget->GetSelectedUnit();
9064  }
9065  else
9066  cptarget = target;
9067 
9068  if (cptarget)
9069  {
9070  target->CastSpell(cptarget, trigger_spell_id, true);
9071  return true;
9072  }
9073  }
9074  return false;
9075  }
9076  // Cast positive spell on enemy target
9077  case 7099: // Curse of Mending
9078  case 39703: // Curse of Mending
9079  case 29494: // Temptation
9080  case 20233: // Improved Lay on Hands (cast on target)
9081  {
9082  target = victim;
9083  break;
9084  }
9085  // Ruby Drake, Evasive Aura
9086  case 50241:
9087  {
9088  if( GetAura(50240) )
9089  return false;
9090 
9091  break;
9092  }
9093  // Combo points add triggers (need add combopoint only for main target, and after possible combopoints reset)
9094  case 15250: // Rogue Setup
9095  {
9096  // applied only for main target
9097  if (!victim || (GetTypeId() == TYPEID_PLAYER && victim != ToPlayer()->GetSelectedUnit()))
9098  return false;
9099  break; // continue normal case
9100  }
9101  // Finish movies that add combo
9102  case 14189: // Seal Fate (Netherblade set)
9103  case 14157: // Ruthlessness
9104  {
9105  if (!victim || victim == this)
9106  return false;
9107  // Need add combopoint AFTER finish movie (or they dropped in finish phase)
9108  break;
9109  }
9110  // Item - Druid T10 Balance 2P Bonus
9111  case 16870:
9112  {
9113  if (HasAura(70718))
9114  CastSpell(this, 70721, true);
9115  RemoveAurasDueToSpell(trigger_spell_id);
9116  break;
9117  }
9118  // Shamanistic Rage triggered spell
9119  case 30824:
9120  {
9121  basepoints0 = int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), triggerAmount));
9122  break;
9123  }
9124  // Enlightenment (trigger only from mana cost spells)
9125  case 35095:
9126  {
9127  if (!procSpell || procSpell->PowerType != POWER_MANA || (procSpell->ManaCost == 0 && procSpell->ManaCostPercentage == 0 && procSpell->ManaCostPerlevel == 0))
9128  return false;
9129  break;
9130  }
9131  // Demonic Pact
9132  case 48090:
9133  {
9134  // Get talent aura from owner
9135  if (IsPet())
9136  if (Unit* owner = GetOwner())
9137  {
9138  if (HasSpellCooldown(trigger_spell_id))
9139  return false;
9140  AddSpellCooldown(trigger_spell_id, 0, cooldown);
9141 
9142  if (AuraEffect* aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0))
9143  {
9144  basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonusDone(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); // TODO: Is it right?
9145  CastCustomSpell(this, trigger_spell_id, &basepoints0, &basepoints0, nullptr, true, castItem, triggeredByAura);
9146  return true;
9147  }
9148  }
9149  break;
9150  }
9151  case 46916: // Slam! (Bloodsurge proc)
9152  case 52437: // Sudden Death
9153  {
9154  // Item - Warrior T10 Melee 4P Bonus
9155  if (AuraEffect const* aurEff = GetAuraEffect(70847, 0))
9156  {
9157  if (!roll_chance_i(aurEff->GetAmount()))
9158  {
9159  // Xinef: dont allow normal proc to override set one
9160  if (GetAura((trigger_spell_id == 46916) ? 71072 : 71069))
9161  return false;
9162  // Xinef: just to be sure
9163  RemoveAurasDueToSpell(70849);
9164  break;
9165  }
9166 
9167  // Xinef: fully remove all auras and reapply once more
9168  RemoveAurasDueToSpell(70849);
9169  RemoveAurasDueToSpell(71072);
9170  RemoveAurasDueToSpell(71069);
9171 
9172  CastSpell(this, 70849, true, castItem, triggeredByAura); // Extra Charge!
9173  if (trigger_spell_id == 46916)
9174  CastSpell(this, 71072, true, castItem, triggeredByAura); // Slam GCD Reduced
9175  else
9176  CastSpell(this, 71069, true, castItem, triggeredByAura); // Execute GCD Reduced
9177  }
9178  break;
9179  }
9180  // Sword and Board
9181  case 50227:
9182  {
9183  // Remove cooldown on Shield Slam
9184  if (GetTypeId() == TYPEID_PLAYER)
9186  break;
9187  }
9188  // Maelstrom Weapon
9189  case 53817:
9190  {
9191  // have rank dependent proc chance, ignore too often cases
9192  // PPM = 2.5 * (rank of talent),
9193  uint32 rank = auraSpellInfo->GetRank();
9194  // 5 rank -> 100% 4 rank -> 80% and etc from full rate
9195  if (!roll_chance_i(20 * rank))
9196  return false;
9197 
9198  // Item - Shaman T10 Enhancement 4P Bonus
9199  if (AuraEffect const* aurEff = GetAuraEffect(70832, 0))
9200  if (Aura const* maelstrom = GetAura(53817))
9201  // xinef: we have 4 charges and all proc conditions are met - aura reaches 5 charges
9202  if ((maelstrom->GetStackAmount() == 4) && roll_chance_i(aurEff->GetAmount()))
9203  CastSpell(this, 70831, true, castItem, triggeredByAura);
9204 
9205  break;
9206  }
9207  // Astral Shift
9208  case 52179:
9209  {
9210  if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) || this == victim)
9211  return false;
9212 
9213  // Need stun, fear or silence mechanic
9214  if (!(procSpell->GetAllEffectsMechanicMask() & ((1 << MECHANIC_SILENCE) | (1 << MECHANIC_STUN) | (1 << MECHANIC_FEAR))))
9215  return false;
9216  break;
9217  }
9218  // Glyph of Death's Embrace
9219  case 58679:
9220  {
9221  // Proc only from healing part of Death Coil. Check is essential as all Death Coil spells have 0x2000 mask in SpellFamilyFlags
9222  if (!procSpell || !(procSpell->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && procSpell->SpellFamilyFlags[0] == 0x80002000))
9223  return false;
9224  break;
9225  }
9226  // Glyph of Death Grip
9227  case 58628:
9228  {
9229  // remove cooldown of Death Grip
9230  if (GetTypeId() == TYPEID_PLAYER)
9231  ToPlayer()->RemoveSpellCooldown(49576, true);
9232  return true;
9233  }
9234  // Savage Defense
9235  case 62606:
9236  {
9237  basepoints0 = CalculatePct(triggerAmount, GetTotalAttackPowerValue(BASE_ATTACK));
9238  break;
9239  }
9240  // Body and Soul
9241  case 64128:
9242  case 65081:
9243  {
9244  // Proc only from PW:S cast
9245  if (!(procSpell->SpellFamilyFlags[0] & 0x00000001))
9246  return false;
9247  break;
9248  }
9249  // Culling the Herd
9250  case 70893:
9251  {
9252  // check if we're doing a critical hit
9253  if (!(procSpell->SpellFamilyFlags[1] & 0x10000000) && (procEx != PROC_EX_CRITICAL_HIT))
9254  return false;
9255  // check if we're procced by Claw, Bite or Smack (need to use the spell icon ID to detect it)
9256  if (!(procSpell->SpellIconID == 262 || procSpell->SpellIconID == 1680 || procSpell->SpellIconID == 473))
9257  return false;
9258  break;
9259  }
9260  // Fingers of Frost, synchronise with Frostbite
9261  case 44544:
9262  {
9263  // Find Frostbite
9265  {
9266  if (!victim)
9267  return false;
9268 
9269  uint8 fofRank = sSpellMgr->GetSpellRank(triggeredByAura->GetId());
9270  uint8 fbRank = sSpellMgr->GetSpellRank(aurEff->GetId());
9271  uint8 chance = uint8(ceil(fofRank * fbRank * 16.6f));
9272 
9273  if (roll_chance_i(chance))
9274  CastSpell(victim, aurEff->GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
9275  }
9276  break;
9277  }
9278  }
9279 
9280  // try detect target manually if not set
9281  if (target == nullptr)
9282  target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim;
9283 
9284  if (cooldown)
9285  {
9286  if (HasSpellCooldown(triggerEntry->Id))
9287  return false;
9288 
9289  AddSpellCooldown(triggerEntry->Id, 0, cooldown);
9290  }
9291 
9292  if(basepoints0)
9293  CastCustomSpell(target, triggerEntry->Id, &basepoints0, nullptr, nullptr, true, castItem, triggeredByAura);
9294  else
9295  CastSpell(target, triggerEntry->Id, true, castItem, triggeredByAura);
9296 
9297  return true;
9298 }
9299 
9300 bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown)
9301 {
9302  int32 scriptId = triggeredByAura->GetMiscValue();
9303 
9304  if (!victim || !victim->IsAlive())
9305  return false;
9306 
9307  Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
9308  ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : nullptr;
9309 
9310  uint32 triggered_spell_id = 0;
9311 
9312  switch (scriptId)
9313  {
9314  case 836: // Improved Blizzard (Rank 1)
9315  {
9316  if (!procSpell || procSpell->SpellVisual[0] != 9487)
9317  return false;
9318  triggered_spell_id = 12484;
9319  break;
9320  }
9321  case 988: // Improved Blizzard (Rank 2)
9322  {
9323  if (!procSpell || procSpell->SpellVisual[0] != 9487)
9324  return false;
9325  triggered_spell_id = 12485;
9326  break;
9327  }
9328  case 989: // Improved Blizzard (Rank 3)
9329  {
9330  if (!procSpell || procSpell->SpellVisual[0] != 9487)
9331  return false;
9332  triggered_spell_id = 12486;
9333  break;
9334  }
9335  case 4533: // Dreamwalker Raiment 2 pieces bonus
9336  {
9337  // Chance 50%
9338  if (!roll_chance_i(50))
9339  return false;
9340 
9341  switch (victim->getPowerType())
9342  {
9343  case POWER_MANA:
9344  triggered_spell_id = 28722;
9345  break;
9346  case POWER_RAGE:
9347  triggered_spell_id = 28723;
9348  break;
9349  case POWER_ENERGY:
9350  triggered_spell_id = 28724;
9351  break;
9352  default:
9353  return false;
9354  }
9355  break;
9356  }
9357  case 4537: // Dreamwalker Raiment 6 pieces bonus
9358  triggered_spell_id = 28750; // Blessing of the Claw
9359  break;
9360  case 5497: // Improved Mana Gems
9361  triggered_spell_id = 37445; // Mana Surge
9362  break;
9363  case 7010: // Revitalize - can proc on full hp target
9364  case 7011:
9365  case 7012:
9366  {
9367  if (!roll_chance_i(triggeredByAura->GetAmount()))
9368  return false;
9369  switch (victim->getPowerType())
9370  {
9371  case POWER_MANA:
9372  triggered_spell_id = 48542;
9373  break;
9374  case POWER_RAGE:
9375  triggered_spell_id = 48541;
9376  break;
9377  case POWER_ENERGY:
9378  triggered_spell_id = 48540;
9379  break;
9380  case POWER_RUNIC_POWER:
9381  triggered_spell_id = 48543;
9382  break;
9383  default:
9384  break;
9385  }
9386  break;
9387  }
9388  default:
9389  break;
9390  }
9391 
9392  // not processed
9393  if (!triggered_spell_id)
9394  return false;
9395 
9396  // standard non-dummy case
9397  SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
9398 
9399  if (!triggerEntry)
9400  {
9401  LOG_ERROR("entities.unit", "Unit::HandleOverrideClassScriptAuraProc: Spell %u triggering for class script id %u", triggered_spell_id, scriptId);
9402  return false;
9403  }
9404 
9405  if (cooldown)
9406  {
9407  if (HasSpellCooldown(triggered_spell_id))
9408  return false;
9409 
9410  AddSpellCooldown(triggered_spell_id, 0, cooldown);
9411  }
9412 
9413  CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura);
9414 
9415  return true;
9416 }
9417 
9418 void Unit::setPowerType(Powers new_powertype)
9419 {
9420  SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype);
9421 
9422  if (GetTypeId() == TYPEID_PLAYER)
9423  {
9424  if (ToPlayer()->GetGroup())
9426  }
9427  else if (Pet* pet = ToCreature()->ToPet())
9428  {
9429  if (pet->isControlled())
9430  {
9431  Unit* owner = GetOwner();
9432  if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
9434  }
9435  }
9436 
9437  float powerMultiplier = 1.0f;
9438  if (!IsPet())
9439  if (Creature* creature = ToCreature())
9440  powerMultiplier = creature->GetCreatureTemplate()->ModMana;
9441 
9442  switch (new_powertype)
9443  {
9444  default:
9445  case POWER_MANA:
9446  break;
9447  case POWER_RAGE:
9449  SetPower(POWER_RAGE, 0);
9450  break;
9451  case POWER_FOCUS:
9454  break;
9455  case POWER_ENERGY:
9457  break;
9458  case POWER_HAPPINESS:
9461  break;
9462  }
9463 
9464  if (const Player* player = ToPlayer())
9465  if (player->NeedSendSpectatorData())
9466  {
9467  ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "PWT", new_powertype);
9468  ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "MPW", new_powertype == POWER_RAGE || new_powertype == POWER_RUNIC_POWER ? GetMaxPower(new_powertype) / 10 : GetMaxPower(new_powertype));
9469  ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "CPW", new_powertype == POWER_RAGE || new_powertype == POWER_RUNIC_POWER ? GetPower(new_powertype) / 10 : GetPower(new_powertype));
9470  }
9471 }
9472 
9474 {
9475  FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(GetFaction());
9476  if (!entry)
9477  {
9478  static ObjectGuid guid; // prevent repeating spam same faction problem
9479 
9480  if (GetGUID() != guid)
9481  {
9482  if (Player const* player = ToPlayer())
9483  LOG_ERROR("entities.unit", "Player %s has invalid faction (faction template id) #%u", player->GetName().c_str(), GetFaction());
9484  else if (Creature const* creature = ToCreature())
9485  LOG_ERROR("entities.unit", "Creature (template id: %u) has invalid faction (faction template id) #%u", creature->GetCreatureTemplate()->Entry, GetFaction());
9486  else
9487  LOG_ERROR("entities.unit", "Unit (name=%s, type=%u) has invalid faction (faction template id) #%u", GetName().c_str(), uint32(GetTypeId()), GetFaction());
9488 
9489  guid = GetGUID();
9490  }
9491  }
9492  return entry;
9493 }
9494 
9496 {
9498  if (GetTypeId() == TYPEID_UNIT)
9500 }
9501 
9502 // function based on function Unit::UnitReaction from 13850 client
9504 {
9505  // always friendly to self
9506  if (this == target)
9507  return REP_FRIENDLY;
9508 
9509  // always friendly to charmer or owner
9511  return REP_FRIENDLY;
9512 
9513  Player const* selfPlayerOwner = GetAffectingPlayer();
9514  Player const* targetPlayerOwner = target->GetAffectingPlayer();
9515 
9516  // check forced reputation to support SPELL_AURA_FORCE_REACTION
9517  if (selfPlayerOwner)
9518  {
9519  if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry())
9520  if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
9521  return *repRank;
9522  }
9523  else if (targetPlayerOwner)
9524  {
9525  if (FactionTemplateEntry const* selfFactionTemplateEntry = GetFactionTemplateEntry())
9526  if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(selfFactionTemplateEntry))
9527  return *repRank;
9528  }
9529 
9531  {
9533  {
9534  if (selfPlayerOwner && targetPlayerOwner)
9535  {
9536  // always friendly to other unit controlled by player, or to the player himself
9537  if (selfPlayerOwner == targetPlayerOwner)
9538  return REP_FRIENDLY;
9539 
9540  // duel - always hostile to opponent
9541  if (selfPlayerOwner->duel && selfPlayerOwner->duel->opponent == targetPlayerOwner && selfPlayerOwner->duel->startTime != 0)
9542  return REP_HOSTILE;
9543 
9544  // same group - checks dependant only on our faction - skip FFA_PVP for example
9545  if (selfPlayerOwner->IsInRaidWith(targetPlayerOwner))
9546  return REP_FRIENDLY; // return true to allow config option AllowTwoSide.Interaction.Group to work
9547  // however client seems to allow mixed group parties, because in 13850 client it works like:
9548  // return GetFactionReactionTo(GetFactionTemplateEntry(), target);
9549  }
9550 
9551  // check FFA_PVP
9552  if (IsFFAPvP() && target->IsFFAPvP())
9553  return REP_HOSTILE;
9554 
9555  if (selfPlayerOwner)
9556  {
9557  if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry())
9558  {
9559  if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
9560  return *repRank;
9562  {
9563  if (FactionEntry const* targetFactionEntry = sFactionStore.LookupEntry(targetFactionTemplateEntry->faction))
9564  {
9565  if (targetFactionEntry->CanHaveReputation())
9566  {
9567  // check contested flags
9568  if (targetFactionTemplateEntry->factionFlags & FACTION_TEMPLATE_FLAG_ATTACK_PVP_ACTIVE_PLAYERS
9569  && selfPlayerOwner->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
9570  return REP_HOSTILE;
9571 
9572  // if faction has reputation, hostile state depends only from AtWar state
9573  if (selfPlayerOwner->GetReputationMgr().IsAtWar(targetFactionEntry))
9574  return REP_HOSTILE;
9575  return REP_FRIENDLY;
9576  }
9577  }
9578  }
9579  }
9580  }
9581  }
9582  }
9583 
9584  ReputationRank repRank = REP_HATED;
9585 
9586  if (!sScriptMgr->IfNormalReaction(this, target, repRank))
9587  return ReputationRank(repRank);
9588  // do checks dependant only on our faction
9590 }
9591 
9592 ReputationRank Unit::GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, Unit const* target) const
9593 {
9594  // always neutral when no template entry found
9595  if (!factionTemplateEntry)
9596  return REP_NEUTRAL;
9597 
9598  FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry();
9599  if (!targetFactionTemplateEntry)
9600  return REP_NEUTRAL;
9601 
9602  // xinef: check forced reputation for self also
9603  if (Player const* selfPlayerOwner = GetAffectingPlayer())
9604  if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(target->GetFactionTemplateEntry()))
9605  return *repRank;
9606 
9607  if (Player const* targetPlayerOwner = target->GetAffectingPlayer())
9608  {
9609  // check contested flags
9611  && targetPlayerOwner->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
9612  return REP_HOSTILE;
9613  if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry))
9614  return *repRank;
9616  {
9617  if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->faction))
9618  {
9619  if (factionEntry->CanHaveReputation())
9620  {
9621  // CvP case - check reputation, don't allow state higher than neutral when at war
9622  ReputationRank repRank = targetPlayerOwner->GetReputationMgr().GetRank(factionEntry);
9623  if (targetPlayerOwner->GetReputationMgr().IsAtWar(factionEntry))
9624  repRank = std::min(REP_NEUTRAL, repRank);
9625  return repRank;
9626  }
9627  }
9628  }
9629  }
9630 
9631  // common faction based check
9632  if (factionTemplateEntry->IsHostileTo(*targetFactionTemplateEntry))
9633  return REP_HOSTILE;
9634  if (factionTemplateEntry->IsFriendlyTo(*targetFactionTemplateEntry))
9635  return REP_FRIENDLY;
9636  if (targetFactionTemplateEntry->IsFriendlyTo(*factionTemplateEntry))
9637  return REP_FRIENDLY;
9639  return REP_HOSTILE;
9640  // neutral by default
9641  return REP_NEUTRAL;
9642 }
9643 
9644 bool Unit::IsHostileTo(Unit const* unit) const
9645 {
9646  return GetReactionTo(unit) <= REP_HOSTILE;
9647 }
9648 
9649 bool Unit::IsFriendlyTo(Unit const* unit) const
9650 {
9651  return GetReactionTo(unit) >= REP_FRIENDLY;
9652 }
9653 
9655 {
9656  FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
9657  if (!my_faction || !my_faction->faction)
9658  return false;
9659 
9660  FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
9661  if (raw_faction && raw_faction->reputationListID >= 0)
9662  return false;
9663 
9664  return my_faction->IsHostileToPlayers();
9665 }
9666 
9668 {
9669  FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
9670  if (!my_faction || !my_faction->faction)
9671  return true;
9672 
9673  FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
9674  if (raw_faction && raw_faction->reputationListID >= 0)
9675  return false;
9676 
9677  return my_faction->IsNeutralToAll();
9678 }
9679 
9680 bool Unit::Attack(Unit* victim, bool meleeAttack)
9681 {
9682  if (!victim || victim == this)
9683  return false;
9684 
9685  // dead units can neither attack nor be attacked
9686  if (!IsAlive() || !victim->IsAlive())
9687  return false;
9688 
9689  // pussywizard: check map, world, phase >_> multithreading crash fix
9690  if (!IsInMap(victim) || !InSamePhase(victim))
9691  return false;
9692 
9693  // player cannot attack in mount state
9694  if (GetTypeId() == TYPEID_PLAYER && IsMounted())
9695  return false;
9696 
9697  // creatures cannot attack while evading
9698  Creature* creature = ToCreature();
9699  if (creature && creature->IsInEvadeMode())
9700  {
9701  return false;
9702  }
9703 
9704  // creatures should not try to attack the player during polymorph
9705  if (creature && creature->IsPolymorphed())
9706  {
9707  return false;
9708  }
9709 
9710  //if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) // pussywizard: wtf? why having this flag prevents from entering combat? it should just prevent melee attack
9711  // return false;
9712 
9713  // nobody can attack GM in GM-mode
9714  if (victim->GetTypeId() == TYPEID_PLAYER)
9715  {
9716  if (victim->ToPlayer()->IsGameMaster())
9717  return false;
9718  }
9719  else
9720  {
9721  if (victim->ToCreature()->IsEvadingAttacks())
9722  return false;
9723  }
9724 
9725  // Unit with SPELL_AURA_SPIRIT_OF_REDEMPTION can not attack
9727  return false;
9728 
9729  // remove SPELL_AURA_MOD_UNATTACKABLE at attack (in case non-interruptible spells stun aura applied also that not let attack)
9732 
9733  if (m_attacking)
9734  {
9735  if (m_attacking == victim)
9736  {
9737  // switch to melee attack from ranged/magic
9738  if (meleeAttack)
9739  {
9741  {
9743  SendMeleeAttackStart(victim);
9744  return true;
9745  }
9746  }
9748  {
9750  SendMeleeAttackStop(victim);
9751  return true;
9752  }
9753  return false;
9754  }
9755 
9756  // switch target
9758  if (!meleeAttack)
9760  }
9761 
9762  if (m_attacking)
9764 
9765  m_attacking = victim;
9766  m_attacking->_addAttacker(this);
9767 
9768  // Set our target
9769  SetTarget(victim->GetGUID());
9770 
9771  if (meleeAttack)
9773 
9774  // set position before any AI calls/assistance
9775  //if (GetTypeId() == TYPEID_UNIT)
9776  // ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
9777  if (creature && !(IsControllableGuardian() && IsControlledByPlayer()))
9778  {
9779  // should not let player enter combat by right clicking target - doesn't helps
9780  SetInCombatWith(victim);
9781  if (victim->GetTypeId() == TYPEID_PLAYER)
9782  victim->SetInCombatWith(this);
9783  AddThreat(victim, 0.0f);
9784 
9786  creature->CallAssistance();
9788 
9790  }
9791 
9792  // delay offhand weapon attack to next attack time
9795 
9796  if (meleeAttack)
9797  SendMeleeAttackStart(victim);
9798 
9799  return true;
9800 }
9801 
9803 {
9804  if (!m_attacking)
9805  return false;
9806 
9807  Unit* victim = m_attacking;
9808 
9810  m_attacking = nullptr;
9811 
9812  // Clear our target
9814 
9816 
9818 
9819  // reset only at real combat stop
9820  if (Creature* creature = ToCreature())
9821  {
9822  creature->SetNoCallAssistance(false);
9823 
9824  if (creature->HasSearchedAssistance())
9825  {
9826  creature->SetNoSearchAssistance(false);
9827  }
9828  }
9829 
9830  SendMeleeAttackStop(victim);
9831 
9832  return true;
9833 }
9834 
9835 void Unit::CombatStop(bool includingCast)
9836 {
9837  if (includingCast && IsNonMeleeSpellCast(false))
9838  InterruptNonMeleeSpells(false);
9839 
9840  AttackStop();
9842  if (GetTypeId() == TYPEID_PLAYER)
9843  ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
9844  ClearInCombat();
9845 
9846  // xinef: just in case
9847  if (IsPetInCombat() && GetTypeId() != TYPEID_PLAYER)
9848  ClearInPetCombat();
9849 }
9850 
9851 void Unit::CombatStopWithPets(bool includingCast)
9852 {
9853  CombatStop(includingCast);
9854 
9855  for (ControlSet::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
9856  (*itr)->CombatStop(includingCast);
9857 }
9858 
9860 {
9862  return true;
9863 
9864  if (!m_Controlled.empty())
9865  for (ControlSet::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
9866  if ((*itr)->isAttackingPlayer())
9867  return true;
9868 
9869  for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
9870  if (m_SummonSlot[i])
9871  if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i]))
9872  if (summon->isAttackingPlayer())
9873  return true;
9874 
9875  return false;
9876 }
9877 
9879 {
9880  while (!m_attackers.empty())
9881  {
9882  AttackerSet::iterator iter = m_attackers.begin();
9883  if (!(*iter)->AttackStop())
9884  {
9885  LOG_ERROR("entities.unit", "WORLD: Unit has an attacker that isn't attacking it!");
9886  m_attackers.erase(iter);
9887  }
9888  }
9889 }
9890 
9892 {
9893  if (apply)
9894  {
9895  if (!HasFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1)))
9896  {
9897  SetFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1));
9898  Unit::AuraMap& tAuras = GetOwnedAuras();
9899  for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end(); ++itr)
9900  {
9901  if( (*itr).second->IsRemoved() )
9902  continue;
9903 
9904  if( (*itr).second->GetSpellInfo()->CasterAuraState == flag )
9905  if( AuraApplication* aurApp = (*itr).second->GetApplicationOfTarget(GetGUID()) )
9906  (*itr).second->HandleAllEffects(aurApp, AURA_EFFECT_HANDLE_REAL, true);
9907  }
9908  }
9909  }
9910  else
9911  {
9912  if (HasFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1)))
9913  {
9914  RemoveFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1));
9915 
9916  if (flag != AURA_STATE_ENRAGE) // enrage aura state triggering continues auras
9917  {
9918  Unit::AuraMap& tAuras = GetOwnedAuras();
9919  for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end(); ++itr)
9920  {
9921  if( (*itr).second->GetSpellInfo()->CasterAuraState == flag )
9922  if( AuraApplication* aurApp = (*itr).second->GetApplicationOfTarget(GetGUID()) )
9923  (*itr).second->HandleAllEffects(aurApp, AURA_EFFECT_HANDLE_REAL, false);
9924  }
9925  }
9926  }
9927  }
9928 }
9929 
9931 {
9933  for (AuraStateAurasMap::const_iterator itr = m_auraStateAuras.begin(); itr != m_auraStateAuras.end(); ++itr)
9934  if ((1 << (itr->first - 1)) & PER_CASTER_AURA_STATE_MASK)
9935  if (itr->second->GetBase()->GetCasterGUID() == target->GetGUID())
9936  auraStates |= (1 << (itr->first - 1));
9937 
9938  return auraStates;
9939 }
9940 
9941 bool Unit::HasAuraState(AuraStateType flag, SpellInfo const* spellProto, Unit const* Caster) const
9942 {
9943  if (Caster)
9944  {
9945  if (spellProto)
9946  {
9948  for (AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
9949  if ((*j)->IsAffectedOnSpell(spellProto))
9950  return true;
9951  }
9952  // Check per caster aura state
9953  // If aura with aurastate by caster not found return false
9954  if ((1 << (flag - 1)) & PER_CASTER_AURA_STATE_MASK)
9955  {
9956  AuraStateAurasMapBounds range = m_auraStateAuras.equal_range(flag);
9957  for (AuraStateAurasMap::const_iterator itr = range.first; itr != range.second; ++itr)
9958  if (itr->second->GetBase()->GetCasterGUID() == Caster->GetGUID())
9959  return true;
9960  return false;
9961  }
9962  }
9963 
9964  return HasFlag(UNIT_FIELD_AURASTATE, 1 << (flag - 1));
9965 }
9966 
9968 {
9969  if (GetOwnerGUID() == owner)
9970  return;
9971 
9973  if (!owner)
9974  return;
9975 
9976  m_applyResilience = !IsVehicle() && owner.IsPlayer();
9977 
9978  // Update owner dependent fields
9979  Player* player = ObjectAccessor::GetPlayer(*this, owner);
9980  if (!player || !player->HaveAtClient(this)) // if player cannot see this unit yet, he will receive needed data with create object
9981  return;
9982 
9984 
9985  UpdateData udata;
9986  WorldPacket packet;
9987  BuildValuesUpdateBlockForPlayer(&udata, player);
9988  udata.BuildPacket(&packet);
9989  player->SendDirectMessage(&packet);
9990 
9992 }
9993 
9995 {
9996  if (ObjectGuid ownerGUID = GetOwnerGUID())
9997  return ObjectAccessor::GetUnit(*this, ownerGUID);
9998 
9999  return nullptr;
10000 }
10001 
10003 {
10004  if (ObjectGuid charmerGUID = GetCharmerGUID())
10005  return ObjectAccessor::GetUnit(*this, charmerGUID);
10006 
10007  return nullptr;
10008 }
10009 
10011 {
10013  if (guid.IsPlayer())
10014  return ObjectAccessor::GetPlayer(*this, guid);
10015 
10016  return const_cast<Unit*>(this)->ToPlayer();
10017 }
10018 
10020 {
10021  if (!GetCharmerOrOwnerGUID())
10022  return const_cast<Unit*>(this)->ToPlayer();
10023 
10024  if (Unit* owner = GetCharmerOrOwner())
10025  return owner->GetCharmerOrOwnerPlayerOrPlayerItself();
10026 
10027  return nullptr;
10028 }
10029 
10031 {
10032  if (ObjectGuid pet_guid = GetMinionGUID())
10033  {
10034  if (Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, pet_guid))
10035  if (pet->HasUnitTypeMask(UNIT_MASK_MINION))
10036  return (Minion*)pet;
10037 
10038  LOG_ERROR("entities.unit", "Unit::GetFirstMinion: Minion %s not exist.", pet_guid.ToString().c_str());
10039  const_cast<Unit*>(this)->SetMinionGUID(ObjectGuid::Empty);
10040  }
10041 
10042  return nullptr;
10043 }
10044 
10046 {
10047  if (ObjectGuid pet_guid = GetPetGUID())
10048  {
10049  if (Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, pet_guid))
10050  if (pet->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
10051  return (Guardian*)pet;
10052 
10053  LOG_FATAL("entities.unit", "Unit::GetGuardianPet: Guardian %s not exist.", pet_guid.ToString().c_str());
10054  const_cast<Unit*>(this)->SetPetGUID(ObjectGuid::Empty);
10055  }
10056 
10057  return nullptr;
10058 }
10059 
10061 {
10062  if (ObjectGuid charm_guid = GetCharmGUID())
10063  {
10064  if (Unit* pet = ObjectAccessor::GetUnit(*this, charm_guid))
10065  return pet;
10066 
10067  LOG_ERROR("entities.unit", "Unit::GetCharm: Charmed creature %s not exist.", charm_guid.ToString().c_str());
10068  const_cast<Unit*>(this)->SetGuidValue(UNIT_FIELD_CHARM, ObjectGuid::Empty);
10069  }
10070 
10071  return nullptr;
10072 }
10073 
10074 void Unit::SetMinion(Minion* minion, bool apply)
10075 {
10076  LOG_DEBUG("entities.unit", "SetMinion %u for %u, apply %u", minion->GetEntry(), GetEntry(), apply);
10077 
10078  if (apply)
10079  {
10080  if (minion->GetOwnerGUID())
10081  {
10082  LOG_FATAL("entities.unit", "SetMinion: Minion %u is not the minion of owner %u", minion->GetEntry(), GetEntry());
10083  return;
10084  }
10085 
10086  minion->SetOwnerGUID(GetGUID());
10087 
10088  m_Controlled.insert(minion);
10089 
10090  if (GetTypeId() == TYPEID_PLAYER)
10091  {
10092  minion->m_ControlledByPlayer = true;
10094  }
10095 
10096  // Can only have one pet. If a new one is summoned, dismiss the old one.
10097  if (minion->IsGuardianPet())
10098  {
10099  if (Guardian* oldPet = GetGuardianPet())
10100  {
10101  if (oldPet != minion && (oldPet->IsPet() || minion->IsPet() || oldPet->GetEntry() != minion->GetEntry()))
10102  {
10103  // remove existing minion pet
10104  if (oldPet->IsPet())
10105  ((Pet*)oldPet)->Remove(PET_SAVE_AS_CURRENT);
10106  else
10107  oldPet->UnSummon();
10108  SetPetGUID(minion->GetGUID());
10110  }
10111  }
10112  else
10113  {
10114  SetPetGUID(minion->GetGUID());
10116  }
10117  }
10118 
10120  {
10122  }
10123 
10124  if (minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET)
10125  {
10126  SetCritterGUID(minion->GetGUID());
10127  }
10128 
10129  // PvP, FFAPvP
10131 
10132  // FIXME: hack, speed must be set only at follow
10133  if (GetTypeId() == TYPEID_PLAYER && minion->IsPet())
10134  for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
10135  minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
10136 
10137  // Ghoul pets have energy instead of mana (is anywhere better place for this code?)
10138  if (minion->IsPetGhoul() || minion->GetEntry() == 24207 /*ENTRY_ARMY_OF_THE_DEAD*/)
10139  minion->setPowerType(POWER_ENERGY);
10140 
10141  if (GetTypeId() == TYPEID_PLAYER)
10142  {
10143  // Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
10144  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
10145 
10146  if (spellInfo && spellInfo->IsCooldownStartedOnEvent())
10147  ToPlayer()->AddSpellAndCategoryCooldowns(spellInfo, 0, nullptr, true);
10148  }
10149  }
10150  else
10151  {
10152  if (minion->GetOwnerGUID() != GetGUID())
10153  {
10154  LOG_FATAL("entities.unit", "SetMinion: Minion %u is not the minion of owner %u", minion->GetEntry(), GetEntry());
10155  return;
10156  }
10157 
10158  m_Controlled.erase(minion);
10159 
10160  if (minion->m_Properties && minion->m_Properties->Type == SUMMON_TYPE_MINIPET)
10161  {
10162  if (GetCritterGUID() == minion->GetGUID())
10164  }
10165 
10166  if (minion->IsGuardianPet())
10167  {
10168  if (GetPetGUID() == minion->GetGUID())
10170  }
10171  else if (minion->IsTotem())
10172  {
10173  // All summoned by totem minions must disappear when it is removed.
10174  if (SpellInfo const* spInfo = sSpellMgr->GetSpellInfo(minion->ToTotem()->GetSpell()))
10175  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
10176  {
10177  if (spInfo->Effects[i].Effect != SPELL_EFFECT_SUMMON)
10178  continue;
10179 
10180  RemoveAllMinionsByEntry(spInfo->Effects[i].MiscValue);
10181  }
10182  }
10183 
10184  if (GetTypeId() == TYPEID_PLAYER)
10185  {
10186  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
10187  // Remove infinity cooldown
10188  if (spellInfo && spellInfo->IsCooldownStartedOnEvent())
10189  ToPlayer()->SendCooldownEvent(spellInfo);
10190 
10191  // xinef: clear spell book
10192  if (m_Controlled.empty())
10194  }
10195 
10196  //if (minion->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
10197  {
10198  if (RemoveGuidValue(UNIT_FIELD_SUMMON, minion->GetGUID()))
10199  {
10200  // Check if there is another minion
10201  for (ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
10202  {
10203  // do not use this check, creature do not have charm guid
10204  //if (GetCharmGUID() == (*itr)->GetGUID())
10205  if (GetGUID() == (*itr)->GetCharmerGUID())
10206  continue;
10207 
10208  //ASSERT((*itr)->GetOwnerGUID() == GetGUID());
10209  if ((*itr)->GetOwnerGUID() != GetGUID())
10210  {
10211  OutDebugInfo();
10212  (*itr)->OutDebugInfo();
10213  ABORT();
10214  }
10215  ASSERT((*itr)->GetTypeId() == TYPEID_UNIT);
10216 
10217  if (!(*itr)->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
10218  continue;
10219 
10220  if (AddGuidValue(UNIT_FIELD_SUMMON, (*itr)->GetGUID()))
10221  {
10222  // show another pet bar if there is no charm bar
10223  if (GetTypeId() == TYPEID_PLAYER && !GetCharmGUID())
10224  {
10225  if ((*itr)->IsPet())
10227  else
10229  }
10230  }
10231  break;
10232  }
10233  }
10234  }
10235  }
10236 }
10237 
10238 void Unit::GetAllMinionsByEntry(std::list<Creature*>& Minions, uint32 entry)
10239 {
10240  for (Unit::ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end();)
10241  {
10242  Unit* unit = *itr;
10243  ++itr;
10244  if (unit->GetEntry() == entry && unit->GetTypeId() == TYPEID_UNIT
10245  && unit->ToCreature()->IsSummon()) // minion, actually
10246  Minions.push_back(unit->ToCreature());
10247  }
10248 }
10249 
10251 {
10252  for (Unit::ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end();)
10253  {
10254  Unit* unit = *itr;
10255  ++itr;
10256  if (unit->GetEntry() == entry && unit->GetTypeId() == TYPEID_UNIT
10257  && unit->ToCreature()->IsSummon()) // minion, actually
10258  unit->ToTempSummon()->UnSummon();
10259  // i think this is safe because i have never heard that a despawned minion will trigger a same minion
10260  }
10261 }
10262 
10263 void Unit::SetCharm(Unit* charm, bool apply)
10264 {
10265  if (apply)
10266  {
10267  if (GetTypeId() == TYPEID_PLAYER)
10268  {
10269  if (!AddGuidValue(UNIT_FIELD_CHARM, charm->GetGUID()))
10270  LOG_FATAL("entities.unit", "Player %s is trying to charm unit %u, but it already has a charmed unit %s", GetName().c_str(), charm->GetEntry(), GetCharmGUID().ToString().c_str());
10271 
10272  charm->m_ControlledByPlayer = true;
10273  // TODO: maybe we can use this flag to check if controlled by player
10275  }
10276  else
10277  charm->m_ControlledByPlayer = false;
10278 
10279  // PvP, FFAPvP
10281 
10282  if (!charm->AddGuidValue(UNIT_FIELD_CHARMEDBY, GetGUID()))
10283  LOG_FATAL("entities.unit", "Unit %u is being charmed, but it already has a charmer %s", charm->GetEntry(), charm->GetCharmerGUID().ToString().c_str());
10284 
10286  charm->SetWalk(false);
10287 
10288  m_Controlled.insert(charm);
10289  }
10290  else
10291  {
10292  if (GetTypeId() == TYPEID_PLAYER)
10293  {
10294  if (!RemoveGuidValue(UNIT_FIELD_CHARM, charm->GetGUID()))
10295  LOG_FATAL("entities.unit", "Player %s is trying to uncharm unit %u, but it has another charmed unit %s", GetName().c_str(), charm->GetEntry(), GetCharmGUID().ToString().c_str());
10296  }
10297 
10299  LOG_FATAL("entities.unit", "Unit %u is being uncharmed, but it has another charmer %s", charm->GetEntry(), charm->GetCharmerGUID().ToString().c_str());
10300 
10301  if (charm->GetTypeId() == TYPEID_PLAYER)
10302  {
10303  charm->m_ControlledByPlayer = true;
10305  charm->ToPlayer()->UpdatePvPState();
10306  }
10307  else if (Player* player = charm->GetCharmerOrOwnerPlayerOrPlayerItself())
10308  {
10309  charm->m_ControlledByPlayer = true;
10311  charm->SetByteValue(UNIT_FIELD_BYTES_2, 1, player->GetByteValue(UNIT_FIELD_BYTES_2, 1));
10312 
10313  // Xinef: skip controlled erase if charmed unit is owned by charmer
10314  if (charm->IsInWorld() && !charm->IsDuringRemoveFromWorld() && player->GetGUID() == this->GetGUID() && (charm->IsPet() || charm->HasUnitTypeMask(UNIT_MASK_MINION)))
10315  return;
10316  }
10317  else
10318  {
10319  charm->m_ControlledByPlayer = false;
10321  charm->SetByteValue(UNIT_FIELD_BYTES_2, 1, 0);
10322  }
10323 
10324  m_Controlled.erase(charm);
10325  }
10326 }
10327 
10328 int32 Unit::DealHeal(Unit* healer, Unit* victim, uint32 addhealth)
10329 {
10330  int32 gain = 0;
10331 
10332  if (healer)
10333  {
10334  if (victim->IsAIEnabled)
10335  victim->GetAI()->HealReceived(healer, addhealth);
10336 
10337  if (healer->IsAIEnabled)
10338  healer->GetAI()->HealDone(victim, addhealth);
10339  }
10340 
10341  if (addhealth)
10342  gain = victim->ModifyHealth(int32(addhealth));
10343 
10344  // Hook for OnHeal Event
10345  sScriptMgr->OnHeal(healer, victim, (uint32&)gain);
10346 
10347  Unit* unit = healer;
10348 
10349  if (healer && healer->GetTypeId() == TYPEID_UNIT && healer->ToCreature()->IsTotem())
10350  unit = healer->GetOwner();
10351 
10352  if (!unit)
10353  return gain;
10354 
10355  if (Player* player = unit->ToPlayer())
10356  {
10357  if (Battleground* bg = player->GetBattleground())
10358  bg->UpdatePlayerScore(player, SCORE_HEALING_DONE, gain);
10359 
10360  // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
10361  if (gain && player->InBattleground()) // pussywizard: InBattleground() optimization
10362  player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, victim);
10363 
10364  //player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth); // pussywizard: optimization
10365  }
10366 
10367  /*if (Player* player = victim->ToPlayer())
10368  {
10369  //player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain); // pussywizard: optimization
10370  //player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth); // pussywizard: optimization
10371  }*/
10372 
10373  return gain;
10374 }
10375 
10376 bool RedirectSpellEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
10377 {
10378  if (Unit* auraOwner = ObjectAccessor::GetUnit(_self, _auraOwnerGUID))
10379  {
10380  // Xinef: already removed
10381  if (!auraOwner->HasAuraType(SPELL_AURA_SPELL_MAGNET))
10382  return true;
10383 
10384  Unit::AuraEffectList const& magnetAuras = auraOwner->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET);
10385  for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
10386  if (*itr == _auraEffect)
10387  {
10388  (*itr)->GetBase()->DropCharge(AURA_REMOVE_BY_DEFAULT);
10389  return true;
10390  }
10391  }
10392 
10393  return true;
10394 }
10395 
10397 {
10398  // Patch 1.2 notes: Spell Reflection no longer reflects abilities
10400  return victim;
10401 
10403  for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
10404  {
10405  if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner())
10406  if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK
10407  //&& spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK
10408  && _IsValidAttackTarget(magnet, spellInfo)
10409  /*&& IsWithinLOSInMap(magnet)*/)
10410  {
10411  // Xinef: We should choose minimum between flight time and queue time as in reflect, however we dont know flight time at this point, use arbitrary small number
10412  magnet->m_Events.AddEvent(new RedirectSpellEvent(*magnet, victim->GetGUID(), *itr), magnet->m_Events.CalculateQueueTime(100));
10413 
10414  if (magnet->IsTotem())
10415  {
10416  uint64 queueTime = magnet->m_Events.CalculateQueueTime(100);
10417  if (spellInfo->Speed > 0.0f)
10418  {
10419  float dist = GetDistance(magnet->GetPositionX(), magnet->GetPositionY(), magnet->GetPositionZ());
10420  if (dist < 5.0f)
10421  dist = 5.0f;
10422  queueTime = magnet->m_Events.CalculateTime((uint64)floor(dist / spellInfo->Speed * 1000.0f));
10423  }
10424 
10425  magnet->m_Events.AddEvent(new KillMagnetEvent(*magnet), queueTime);
10426  }
10427 
10428  return magnet;
10429  }
10430  }
10431  return victim;
10432 }
10433 
10435 {
10436  AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER);
10437  for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i)
10438  {
10439  if (Unit* magnet = (*i)->GetBase()->GetCaster())
10440  if (_IsValidAttackTarget(magnet, spellInfo) && magnet->IsWithinLOSInMap(this)
10441  && (!spellInfo || (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK
10442  && spellInfo->CheckTarget(this, magnet, false) == SPELL_CAST_OK)))
10443  if (roll_chance_i((*i)->GetAmount()))
10444  {
10445  (*i)->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
10446  return magnet;
10447  }
10448  }
10449  return victim;
10450 }
10451 
10453 {
10454  // Sequence: charmed, pet, other guardians
10455  Unit* unit = GetCharm();
10456  if (!unit)
10457  if (ObjectGuid guid = GetMinionGUID())
10458  unit = ObjectAccessor::GetUnit(*this, guid);
10459 
10460  return unit;
10461 }
10462 
10463 void Unit::RemoveAllControlled(bool onDeath /*= false*/)
10464 {
10465  // possessed pet and vehicle
10466  if (GetTypeId() == TYPEID_PLAYER)
10468 
10469  while (!m_Controlled.empty())
10470  {
10471  Unit* target = *m_Controlled.begin();
10472  m_Controlled.erase(m_Controlled.begin());
10473  if (target->GetCharmerGUID() == GetGUID())
10474  {
10475  target->RemoveCharmAuras();
10476  }
10477  else if (target->GetOwnerGUID() == GetGUID() && target->IsSummon())
10478  {
10479  if (!(onDeath && !IsPlayer() && target->IsGuardian()))
10480  {
10481  target->ToTempSummon()->UnSummon();
10482  }
10483  }
10484  else
10485  {
10486  LOG_ERROR("entities.unit", "Unit %u is trying to release unit %u which is neither charmed nor owned by it", GetEntry(), target->GetEntry());
10487  }
10488  }
10489 }
10490 
10492 {
10493  Player* player = nullptr;
10494  if (GetTypeId() == TYPEID_PLAYER)
10495  player = ToPlayer();
10496  // Should we enable this also for charmed units?
10497  else if (GetTypeId() == TYPEID_UNIT && IsPet())
10498  player = GetOwner()->ToPlayer();
10499 
10500  if (!player)
10501  return nullptr;
10502  Group* group = player->GetGroup();
10503  // When there is no group check pet presence
10504  if (!group)
10505  {
10506  // We are pet now, return owner
10507  if (player != this)
10508  return IsWithinDistInMap(player, radius) ? player : nullptr;
10509  Unit* pet = GetGuardianPet();
10510  // No pet, no group, nothing to return
10511  if (!pet)
10512  return nullptr;
10513  // We are owner now, return pet
10514  return IsWithinDistInMap(pet, radius) ? pet : nullptr;
10515  }
10516 
10517  std::vector<Unit*> nearMembers;
10518  // reserve place for players and pets because resizing vector every unit push is unefficient (vector is reallocated then)
10519  nearMembers.reserve(group->GetMembersCount() * 2);
10520 
10521  for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
10522  if (Player* Target = itr->GetSource())
10523  {
10524  if (Target != this && !IsWithinDistInMap(Target, radius))
10525  continue;
10526 
10527  // IsHostileTo check duel and controlled by enemy
10528  if (Target != this && Target->IsAlive() && !IsHostileTo(Target))
10529  nearMembers.push_back(Target);
10530 
10531  // Push player's pet to vector
10532  if (Unit* pet = Target->GetGuardianPet())
10533  if (pet != this && pet->IsAlive() && IsWithinDistInMap(pet, radius) && !IsHostileTo(pet))
10534  nearMembers.push_back(pet);
10535  }
10536 
10537  if (nearMembers.empty())
10538  return nullptr;
10539 
10540  uint32 randTarget = urand(0, nearMembers.size() - 1);
10541  return nearMembers[randTarget];
10542 }
10543 
10544 // only called in Player::SetSeer
10545 // so move it to Player?
10547 {
10548  if (m_sharedVision.empty())
10549  {
10550  setActive(true);
10551  SetWorldObject(true);
10552  }
10553  m_sharedVision.insert(player);
10554  player->m_isInSharedVisionOf.insert(this);
10555 }
10556 
10557 // only called in Player::SetSeer
10559 {
10560  m_sharedVision.erase(player);
10561  player->m_isInSharedVisionOf.erase(this);
10562  if (m_sharedVision.empty())
10563  {
10564  setActive(false);
10565  SetWorldObject(false);
10566  }
10567 }
10568 
10570 {
10572 }
10573 
10575 {
10580 }
10581 
10582 void Unit::UnsummonAllTotems(bool onDeath /*= false*/)
10583 {
10584  for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
10585  {
10586  if (!m_SummonSlot[i])
10587  {
10588  continue;
10589  }
10590 
10591  if (Creature* OldTotem = GetMap()->GetCreature(m_SummonSlot[i]))
10592  {
10593  if (OldTotem->IsSummon())
10594  {
10595  if (!(onDeath && !IsPlayer() && OldTotem->IsGuardian()))
10596  {
10597  OldTotem->ToTempSummon()->UnSummon();
10598  }
10599  }
10600  }
10601  }
10602 }
10603 
10604 void Unit::SendHealSpellLog(Unit* victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical)
10605 {
10606  // we guess size
10607  WorldPacket data(SMSG_SPELLHEALLOG, (8 + 8 + 4 + 4 + 4 + 4 + 1 + 1));
10608  data << victim->GetPackGUID();
10609  data << GetPackGUID();
10610  data << uint32(SpellID);
10611  data << uint32(Damage);
10612  data << uint32(OverHeal);
10613  data << uint32(Absorb); // Absorb amount
10614  data << uint8(critical ? 1 : 0);
10615  data << uint8(0); // unused
10616  SendMessageToSet(&data, true);
10617 }
10618 
10619 int32 Unit::HealBySpell(HealInfo& healInfo, bool critical)
10620 {
10621  uint32 heal = healInfo.GetHeal();
10622  sScriptMgr->ModifyHealRecieved(this, healInfo.GetTarget(), heal);
10623  healInfo.SetHeal(heal);
10624 
10625  // calculate heal absorb and reduce healing
10626  CalcHealAbsorb(healInfo);
10627 
10628  int32 gain = Unit::DealHeal(healInfo.GetHealer(), healInfo.GetTarget(), healInfo.GetHeal());
10629  SendHealSpellLog(healInfo.GetTarget(), healInfo.GetSpellInfo()->Id, healInfo.GetHeal(), uint32(healInfo.GetHeal() - gain), healInfo.GetAbsorb(), critical);
10630  return gain;
10631 }
10632 
10633 void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellID, uint32 damage, Powers powerType)
10634 {
10635  WorldPacket data(SMSG_SPELLENERGIZELOG, (8 + 8 + 4 + 4 + 4 + 1));
10636  data << victim->GetPackGUID();
10637  data << GetPackGUID();
10638  data << uint32(spellID);
10639  data << uint32(powerType);
10640  data << uint32(damage);
10641  SendMessageToSet(&data, true);
10642 }
10643 
10644 void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers powerType)
10645 {
10646  SendEnergizeSpellLog(victim, spellID, damage, powerType);
10647  // needs to be called after sending spell log
10648  victim->ModifyPower(powerType, damage);
10649 
10650  if (powerType != POWER_HAPPINESS)
10651  {
10652  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
10653  victim->getHostileRefMgr().threatAssist(this, float(damage) * 0.5f, spellInfo);
10654  }
10655 }
10656 
10657 float Unit::SpellPctDamageModsDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype)
10658 {
10659  if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
10660  return 1.0f;
10661 
10662  // Some spells don't benefit from done mods
10664  return 1.0f;
10665 
10666  // For totems get damage bonus from owner
10667  if (GetTypeId() == TYPEID_UNIT)
10668  {
10669  if (IsTotem())
10670  {
10671  if (Unit* owner = GetOwner())
10672  return owner->SpellPctDamageModsDone(victim, spellProto, damagetype);
10673  }
10674  // Dancing Rune Weapon...
10675  else if (GetEntry() == 27893)
10676  {
10677  if (Unit* owner = GetOwner())
10678  return owner->SpellPctDamageModsDone(victim, spellProto, damagetype);
10679  }
10680  }
10681 
10682  // Done total percent damage auras
10683  float DoneTotalMod = 1.0f;
10684 
10686  for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
10687  {
10688  // prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
10689  if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1 &&
10690  !(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPED_ITEM) && (*i)->GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL)
10691  {
10692  continue;
10693  }
10694 
10695  if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT))
10696  continue;
10697 
10698  if (!sScriptMgr->IsNeedModSpellDamagePercent(this, *i, DoneTotalMod, spellProto))
10699  continue;
10700 
10701  if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
10702  {
10703  if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
10704  AddPct(DoneTotalMod, (*i)->GetAmount());
10705  else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPED_ITEM) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
10706  AddPct(DoneTotalMod, (*i)->GetAmount());
10707  else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
10708  AddPct(DoneTotalMod, (*i)->GetAmount());
10709  }
10710  }
10711 
10712  uint32 creatureTypeMask = victim->GetCreatureTypeMask();
10714  for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
10715  if ((creatureTypeMask & uint32((*i)->GetMiscValue())) && spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT))
10716  AddPct(DoneTotalMod, (*i)->GetAmount());
10717 
10718  // bonus against aurastate
10720  for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i)
10721  if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())) && spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT))
10722  AddPct(DoneTotalMod, (*i)->GetAmount());
10723 
10724  // done scripted mod (take it from owner)
10725  Unit* owner = GetOwner() ? GetOwner() : this;
10726  AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
10727  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
10728  {
10729  // Xinef: self cast is ommited (because of Rage of Rivendare)
10730  if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, damagetype == DOT))
10731  continue;
10732 
10733  // xinef: Molten Fury should work on all spells
10734  switch ((*i)->GetMiscValue())
10735  {
10736  case 4920: // Molten Fury
10737  case 4919:
10738  if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
10739  AddPct(DoneTotalMod, (*i)->GetAmount());
10740  break;
10741  }
10742 
10743  if (!(*i)->IsAffectedOnSpell(spellProto))
10744  continue;
10745 
10746  switch ((*i)->GetMiscValue())
10747  {
10748  case 6917: // Death's Embrace
10749  case 6926:
10750  case 6928:
10751  {
10752  if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
10753  AddPct(DoneTotalMod, (*i)->GetAmount());
10754  break;
10755  }
10756  // Soul Siphon
10757  case 4992:
10758  case 4993:
10759  {
10760  // effect 1 m_amount
10761  int32 maxPercent = (*i)->GetAmount();
10762  // effect 0 m_amount
10763  int32 stepPercent = CalculateSpellDamage(this, (*i)->GetSpellInfo(), 0);
10764  // count affliction effects and calc additional damage in percentage
10765  int32 modPercent = 0;
10766  AuraApplicationMap const& victimAuras = victim->GetAppliedAuras();
10767  for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
10768  {
10769  Aura const* aura = itr->second->GetBase();
10770  SpellInfo const* m_spell = aura->GetSpellInfo();
10771  if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags[1] & 0x0004071B || m_spell->SpellFamilyFlags[0] & 0x8044C402))
10772  continue;
10773  modPercent += stepPercent * aura->GetStackAmount();
10774  if (modPercent >= maxPercent)
10775  {
10776  modPercent = maxPercent;
10777  break;
10778  }
10779  }
10780  AddPct(DoneTotalMod, modPercent);
10781  break;
10782  }
10783  case 6916: // Death's Embrace
10784  case 6925:
10785  case 6927:
10786  if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, spellProto, this))
10787  AddPct(DoneTotalMod, (*i)->GetAmount());
10788  break;
10789  case 5481: // Starfire Bonus
10790  {
10791  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0))
10792  AddPct(DoneTotalMod, (*i)->GetAmount());
10793  break;
10794  }
10795  // Tundra Stalker
10796  // Merciless Combat
10797  case 7277:
10798  {
10799  // Merciless Combat
10800  if ((*i)->GetSpellInfo()->SpellIconID == 2656)
10801  {
10802  if( (spellProto && spellProto->SpellFamilyFlags[0] & 0x2) || spellProto->SpellFamilyFlags[1] & 0x2 )
10803  if (!victim->HealthAbovePct(35))
10804  AddPct(DoneTotalMod, (*i)->GetAmount());
10805  }
10806  // Tundra Stalker
10807  else
10808  {
10809  // Frost Fever (target debuff)
10810  if (victim->HasAura(55095))
10811  AddPct(DoneTotalMod, (*i)->GetAmount());
10812  break;
10813  }
10814  break;
10815  }
10816  // Rage of Rivendare
10817  case 7293:
10818  {
10819  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
10820  AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
10821  break;
10822  }
10823  // Twisted Faith
10824  case 7377:
10825  {
10826  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
10827  AddPct(DoneTotalMod, (*i)->GetAmount());
10828  break;
10829  }
10830  // Marked for Death
10831  case 7598:
10832  case 7599:
10833  case 7600:
10834  case 7601:
10835  case 7602:
10836  {
10837  if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
10838  AddPct(DoneTotalMod, (*i)->GetAmount());
10839  break;
10840  }
10841  // Dirty Deeds
10842  case 6427:
10843  case 6428:
10844  case 6579:
10845  case 6580:
10846  {
10847  if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
10848  {
10849  // effect 0 has expected value but in negative state
10850  int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
10851  AddPct(DoneTotalMod, bonus);
10852  }
10853  break;
10854  }
10855  }
10856  }
10857 
10858  // Custom scripted damage
10859  switch (spellProto->SpellFamilyName)
10860  {
10861  case SPELLFAMILY_MAGE:
10862  // Ice Lance
10863  if (spellProto->SpellIconID == 186)
10864  {
10865  if (victim->HasAuraState(AURA_STATE_FROZEN, spellProto, this))
10866  {
10867  // Glyph of Ice Lance
10868  if (owner->HasAura(56377) && victim->getLevel() > owner->getLevel())
10869  DoneTotalMod *= 4.0f;
10870  else
10871  DoneTotalMod *= 3.0f;
10872  }
10873  }
10874 
10875  // Torment the weak
10876  if (spellProto->SpellFamilyFlags[0] & 0x20600021 || spellProto->SpellFamilyFlags[1] & 0x9000)
10877  if (victim->HasAuraWithMechanic((1 << MECHANIC_SNARE) | (1 << MECHANIC_SLOW_ATTACK)))
10879  AddPct(DoneTotalMod, aurEff->GetAmount());
10880  break;
10881  case SPELLFAMILY_PRIEST:
10882  // Mind Flay
10883  if (spellProto->SpellFamilyFlags[0] & 0x800000)
10884  {
10885  // Glyph of Shadow Word: Pain
10886  if (AuraEffect* aurEff = GetAuraEffect(55687, 0))
10887  // Increase Mind Flay damage if Shadow Word: Pain present on target
10888  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
10889  AddPct(DoneTotalMod, aurEff->GetAmount());
10890 
10891  // Twisted Faith - Mind Flay part
10893  // Increase Mind Flay damage if Shadow Word: Pain present on target
10894  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, GetGUID()))
10895  AddPct(DoneTotalMod, aurEff->GetAmount());
10896  }
10897  // Smite
10898  else if (spellProto->SpellFamilyFlags[0] & 0x80)
10899  {
10900  // Glyph of Smite
10901  if (AuraEffect* aurEff = GetAuraEffect(55692, 0))
10902  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, GetGUID()))
10903  AddPct(DoneTotalMod, aurEff->GetAmount());
10904  }
10905  // Shadow Word: Death
10906  else if (spellProto->SpellFamilyFlags[1] & 0x2)
10907  {
10908  // Glyph of Shadow Word: Death
10909  if (AuraEffect* aurEff = GetAuraEffect(55682, 1))
10911  AddPct(DoneTotalMod, aurEff->GetAmount());
10912  }
10913 
10914  break;
10915  case SPELLFAMILY_PALADIN:
10916  // Judgement of Vengeance/Judgement of Corruption
10917  if ((spellProto->SpellFamilyFlags[1] & 0x400000) && spellProto->SpellIconID == 2292)
10918  {
10919  // Get stack of Holy Vengeance/Blood Corruption on the target added by caster
10920  uint32 stacks = 0;
10922  for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
10923  if (((*itr)->GetId() == 31803 || (*itr)->GetId() == 53742) && (*itr)->GetCasterGUID() == GetGUID())
10924  {
10925  stacks = (*itr)->GetBase()->GetStackAmount();
10926  break;
10927  }
10928  // + 10% for each application of Holy Vengeance/Blood Corruption on the target
10929  if (stacks)
10930  AddPct(DoneTotalMod, 10 * stacks);
10931  }
10932  break;
10933  case SPELLFAMILY_DRUID:
10934  // Thorns
10935  if (spellProto->SpellFamilyFlags[0] & 0x100)
10936  {
10937  // Brambles
10938  if (AuraEffect* aurEff = GetAuraEffectOfRankedSpell(16836, 0))
10939  AddPct(DoneTotalMod, aurEff->GetAmount());
10940  }
10941  break;
10942  case SPELLFAMILY_WARLOCK:
10943  // Fire and Brimstone
10944  if (spellProto->SpellFamilyFlags[1] & 0x00020040)
10945  if (victim->HasAuraState(AURA_STATE_CONFLAGRATE))
10946  {
10948  for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i)
10949  if ((*i)->GetSpellInfo()->SpellIconID == 3173)
10950  {
10951  AddPct(DoneTotalMod, (*i)->GetAmount());
10952  break;
10953  }
10954  }
10955  // Drain Soul - increased damage for targets under 25 % HP
10956  if (spellProto->SpellFamilyFlags[0] & 0x00004000)
10957  if (!victim->HealthAbovePct(25))
10958  DoneTotalMod *= 4;
10959  // Shadow Bite (15% increase from each dot)
10960  if (spellProto->SpellFamilyFlags[1] & 0x00400000 && IsPet())
10961  if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
10962  AddPct(DoneTotalMod, 15 * count);
10963  break;
10964  case SPELLFAMILY_HUNTER:
10965  // Steady Shot
10966  if (spellProto->SpellFamilyFlags[1] & 0x1)
10967  if (AuraEffect* aurEff = GetAuraEffect(56826, 0)) // Glyph of Steady Shot
10968  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_HUNTER, 0x00004000, 0, 0, GetGUID()))
10969  AddPct(DoneTotalMod, aurEff->GetAmount());
10970  break;
10972  // Improved Icy Touch
10973  if (spellProto->SpellFamilyFlags[0] & 0x2)
10974  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0))
10975  AddPct(DoneTotalMod, aurEff->GetAmount());
10976 
10977  // Glacier Rot
10978  if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
10979  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
10980  if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
10981  AddPct(DoneTotalMod, aurEff->GetAmount());
10982  break;
10983  }
10984 
10985  return DoneTotalMod;
10986 }
10987 
10988 uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, float TotalMod, uint32 stack)
10989 {
10990  if (!spellProto || !victim || damagetype == DIRECT_DAMAGE)
10991  return pdamage;
10992 
10993  // Some spells don't benefit from done mods
10995  return pdamage;
10996 
10997  // For totems get damage bonus from owner
10998  if (GetTypeId() == TYPEID_UNIT)
10999  {
11000  if (IsTotem())
11001  {
11002  if (Unit* owner = GetOwner())
11003  return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, TotalMod, stack);
11004  }
11005  // Dancing Rune Weapon...
11006  else if (GetEntry() == 27893)
11007  {
11008  if (Unit* owner = GetOwner())
11009  return owner->SpellDamageBonusDone(victim, spellProto, pdamage, damagetype, TotalMod, stack) / 2;
11010  }
11011  }
11012 
11013  // Done total percent damage auras
11014  float ApCoeffMod = 1.0f;
11015  int32 DoneTotal = 0;
11016  float DoneTotalMod = TotalMod ? TotalMod : SpellPctDamageModsDone(victim, spellProto, damagetype);
11017 
11018  // Config : RATE_CREATURE_X_SPELLDAMAGE & Do Not Modify Pet/Guardian/Mind Controled Damage
11020  DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
11021 
11022  // Some spells don't benefit from pct done mods
11024  {
11025  uint32 creatureTypeMask = victim->GetCreatureTypeMask();
11026  // Add flat bonus from spell damage versus
11028  }
11029 
11030  // done scripted mod (take it from owner)
11031  Unit* owner = GetOwner() ? GetOwner() : this;
11032  AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
11033  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
11034  {
11035  if (!(*i)->IsAffectedOnSpell(spellProto))
11036  continue;
11037 
11038  switch ((*i)->GetMiscValue())
11039  {
11040  case 4418: // Increased Shock Damage
11041  case 4554: // Increased Lightning Damage
11042  case 4555: // Improved Moonfire
11043  case 5142: // Increased Lightning Damage
11044  case 5147: // Improved Consecration / Libram of Resurgence
11045  case 5148: // Idol of the Shooting Star
11046  case 6008: // Increased Lightning Damage
11047  case 8627: // Totem of Hex
11048  {
11049  DoneTotal += (*i)->GetAmount();
11050  break;
11051  }
11052  }
11053  }
11054 
11055  // Custom scripted damage
11056  if (spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
11057  {
11058  // Sigil of the Vengeful Heart
11059  if (spellProto->SpellFamilyFlags[0] & 0x2000)
11060  if (AuraEffect* aurEff = GetAuraEffect(64962, EFFECT_1))
11061  AddPct(DoneTotal, aurEff->GetAmount());
11062 
11063  // Impurity
11064  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 1986, 0))
11065  AddPct(ApCoeffMod, aurEff->GetAmount());
11066 
11067  // Blood Boil - bonus for diseased targets
11068  if (spellProto->SpellFamilyFlags[0] & 0x00040000)
11069  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, GetGUID()))
11070  {
11071  DoneTotal += 95;
11072  ApCoeffMod = 1.5835f;
11073  }
11074  }
11075 
11076  // Done fixed damage bonus auras
11077  int32 DoneAdvertisedBenefit = SpellBaseDamageBonusDone(spellProto->GetSchoolMask());
11078 
11079  // Check for table values
11080  float coeff = 0;
11081  SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
11082  if (bonus)
11083  {
11084  if (damagetype == DOT)
11085  {
11086  coeff = bonus->dot_damage;
11087  if (bonus->ap_dot_bonus > 0)
11088  {
11089  WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
11091  APbonus += GetTotalAttackPowerValue(attType);
11092  DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
11093  }
11094  }
11095  else
11096  {
11097  coeff = bonus->direct_damage;
11098  if (bonus->ap_bonus > 0)
11099  {
11100  WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
11102  APbonus += GetTotalAttackPowerValue(attType);
11103  DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
11104  }
11105  }
11106  }
11107 
11108  // Default calculation
11109  if (coeff && DoneAdvertisedBenefit)
11110  {
11111  float factorMod = CalculateLevelPenalty(spellProto) * stack;
11112 
11113  if (Player* modOwner = GetSpellModOwner())
11114  {
11115  coeff *= 100.0f;
11116  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
11117  coeff /= 100.0f;
11118  }
11119 
11120  DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
11121  }
11122 
11123  float tmpDamage = (float(pdamage) + DoneTotal) * DoneTotalMod;
11124  // apply spellmod to Done damage (flat and pct)
11125  if (Player* modOwner = GetSpellModOwner())
11126  modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
11127 
11128  return uint32(std::max(tmpDamage, 0.0f));
11129 }
11130 
11131 uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
11132 {
11133  if (!spellProto || damagetype == DIRECT_DAMAGE)
11134  return pdamage;
11135 
11136  int32 TakenTotal = 0;
11137  float TakenTotalMod = 1.0f;
11138 
11139  // from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
11140  // multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
11142  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
11143  if (((*i)->GetMiscValue() & spellProto->GetSchoolMask()))
11144  if (spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT))
11145  AddPct(TakenTotalMod, (*i)->GetAmount());
11146 
11147  TakenTotalMod = processDummyAuras(TakenTotalMod);
11148 
11149  // From caster spells
11150  if (caster)
11151  {
11153  for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
11154  if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
11155  if (spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT))
11156  AddPct(TakenTotalMod, (*i)->GetAmount());
11157  }
11158 
11159  if (uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask())
11160  {
11161  int32 modifierMax = 0;
11162  int32 modifierMin = 0;
11164  for (AuraEffectList::const_iterator i = auraEffectList.begin(); i != auraEffectList.end(); ++i)
11165  {
11166  if (!spellProto->ValidateAttribute6SpellDamageMods(caster, *i, damagetype == DOT))
11167  continue;
11168 
11169  // Only death knight spell with this aura, ZOMG!
11170  if ((*i)->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
11171  if (!caster || caster->GetGUID() != (*i)->GetCasterGUID())
11172  continue;
11173 
11174  if (mechanicMask & uint32(1 << (*i)->GetMiscValue()))
11175  {
11176  if ((*i)->GetAmount() > 0)
11177  {
11178  if ((*i)->GetAmount() > modifierMax)
11179  modifierMax = (*i)->GetAmount();
11180  }
11181  else if ((*i)->GetAmount() < modifierMin)
11182  modifierMin = (*i)->GetAmount();
11183  }
11184  }
11185 
11186  AddPct(TakenTotalMod, modifierMax);
11187  AddPct(TakenTotalMod, modifierMin);
11188  }
11189 
11190  int32 TakenAdvertisedBenefit = SpellBaseDamageBonusTaken(spellProto->GetSchoolMask(), damagetype == DOT);
11191 
11192  // Check for table values
11193  float coeff = 0;
11194  SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
11195  if (bonus)
11196  coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
11197 
11198  // Default calculation
11199  if (TakenAdvertisedBenefit)
11200  {
11201  if (coeff <= 0.0f)
11202  {
11203  if (caster)
11204  coeff = caster->CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
11205  else
11206  coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack);
11207  }
11208 
11209  float factorMod = CalculateLevelPenalty(spellProto) * stack;
11210  TakenTotal += int32(TakenAdvertisedBenefit * coeff * factorMod);
11211  }
11212 
11213  // No positive taken bonus, custom attr
11214  if (spellProto->HasAttribute(SPELL_ATTR0_CU_NO_POSITIVE_TAKEN_BONUS) && TakenTotalMod > 1.0f)
11215  {
11216  TakenTotal = 0;
11217  TakenTotalMod = 1.0f;
11218  }
11219 
11220  // xinef: sanctified wrath talent
11221  if (caster && TakenTotalMod < 1.0f && caster->HasAuraType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST))
11222  {
11223  float ignoreModifier = 1.0f - TakenTotalMod;
11224  bool addModifier = false;
11226  for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
11227  if ((*j)->GetMiscValue() & spellProto->SchoolMask)
11228  {
11229  ApplyPct(ignoreModifier, (*j)->GetAmount());
11230  addModifier = true;
11231  }
11232 
11233  if (addModifier)
11234  TakenTotalMod += ignoreModifier;
11235  }
11236 
11237  float tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod;
11238 
11239  return uint32(std::max(tmpDamage, 0.0f));
11240 }
11241 
11242 float Unit::processDummyAuras(float TakenTotalMod) const
11243 {
11244  // note: old code coming from TC, just extracted here to remove the code duplication + solve potential crash
11245  // see: https://github.com/TrinityCore/TrinityCore/commit/c85710e148d75450baedf6632b9ca6fd40b4148e
11246 
11247  // .. taken pct: dummy auras
11248  auto const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
11249  for (auto i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
11250  {
11251  if (!(*i) || !(*i)->GetSpellInfo())
11252  {
11253  continue;
11254  }
11255 
11256  if (auto spellIconId = (*i)->GetSpellInfo()->SpellIconID)
11257  {
11258  switch (spellIconId)
11259  {
11260  // Cheat Death
11261  case 2109:
11262  if ((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)
11263  {
11264  // Patch 2.4.3: The resilience required to reach the 90% damage reduction cap
11265  // is 22.5% critical strike damage reduction, or 444 resilience.
11266  // To calculate for 90%, we multiply the 100% by 4 (22.5% * 4 = 90%)
11267  float mod = -1.0f * GetMeleeCritDamageReduction(400);
11268  AddPct(TakenTotalMod, std::max(mod, float((*i)->GetAmount())));
11269  }
11270  break;
11271  }
11272  }
11273  }
11274  return TakenTotalMod;
11275 }
11276 
11278 {
11279  int32 DoneAdvertisedBenefit = 0;
11280 
11282  for (AuraEffectList::const_iterator i = mDamageDone.begin(); i != mDamageDone.end(); ++i)
11283  if (((*i)->GetMiscValue() & schoolMask) != 0 &&
11284  (*i)->GetSpellInfo()->EquippedItemClass == -1 &&
11285  // -1 == any item class (not wand then)
11286  (*i)->GetSpellInfo()->EquippedItemInventoryTypeMask == 0)
11287  // 0 == any inventory type (not wand then)
11288  DoneAdvertisedBenefit += (*i)->GetAmount();
11289 
11290  if (GetTypeId() == TYPEID_PLAYER)
11291  {
11292  // Base value
11293  DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
11294 
11295  // Damage bonus from stats
11297  for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i)
11298  {
11299  if ((*i)->GetMiscValue() & schoolMask)
11300  {
11301  // stat used stored in miscValueB for this aura
11302  Stats usedStat = Stats((*i)->GetMiscValueB());
11303  DoneAdvertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount()));
11304  }
11305  }
11306  // ... and attack power
11308  for (AuraEffectList::const_iterator i = mDamageDonebyAP.begin(); i != mDamageDonebyAP.end(); ++i)
11309  if ((*i)->GetMiscValue() & schoolMask)
11310  DoneAdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount()));
11311  }
11312  return DoneAdvertisedBenefit;
11313 }
11314 
11316 {
11317  int32 TakenAdvertisedBenefit = 0;
11318 
11320  for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
11321  if (((*i)->GetMiscValue() & schoolMask) != 0)
11322  {
11323  // Xinef: if we have DoT damage type and aura has charges, check if it affects DoTs
11324  // Xinef: required for hemorrhage & rupture / garrote
11325  if (isDoT && (*i)->GetBase()->IsUsingCharges() && !((*i)->GetSpellInfo()->ProcFlags & PROC_FLAG_TAKEN_PERIODIC))
11326  continue;
11327 
11328  TakenAdvertisedBenefit += (*i)->GetAmount();
11329  }
11330 
11331  return TakenAdvertisedBenefit;
11332 }
11333 
11334 float Unit::SpellDoneCritChance(Unit const* /*victim*/, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType, bool skipEffectCheck) const
11335 {
11336  // Mobs can't crit with spells.
11337  if (GetTypeId() == TYPEID_UNIT && !GetSpellModOwner())
11338  return -100.0f;
11339 
11340  // not critting spell
11341  if (spellProto->HasAttribute(SPELL_ATTR2_CANT_CRIT))
11342  return 0.0f;
11343 
11344  // Xinef: check if spell is capable of critting, auras requires special aura to crit so they can be skipped
11345  if (!skipEffectCheck && !spellProto->IsCritCapable())
11346  return 0.0f;
11347 
11348  float crit_chance = 0.0f;
11349  switch (spellProto->DmgClass)
11350  {
11352  {
11353  if (schoolMask & SPELL_SCHOOL_MASK_NORMAL)
11354  crit_chance = 0.0f;
11355  // For other schools
11356  else if (GetTypeId() == TYPEID_PLAYER)
11357  crit_chance = GetFloatValue(static_cast<uint16>(PLAYER_SPELL_CRIT_PERCENTAGE1) + GetFirstSchoolInMask(schoolMask));
11358  else
11359  {
11360  crit_chance = (float)m_baseSpellCritChance;
11362  }
11363  break;
11364  }
11367  {
11368  if (GetTypeId() == TYPEID_PLAYER)
11369  {
11370  switch (attackType)
11371  {
11372  case BASE_ATTACK:
11373  crit_chance = GetFloatValue(PLAYER_CRIT_PERCENTAGE);
11374  break;
11375  case OFF_ATTACK:
11377  break;
11378  case RANGED_ATTACK:
11380  break;
11381  default:
11382  break;
11383  }
11384  }
11385  else
11386  {
11387  crit_chance = 5.0f;
11390  }
11392  break;
11393  }
11394  // values overridden in spellmgr for lifebloom and earth shield
11396  default:
11397  return 0.0f;
11398  }
11399 
11400  // percent done
11401  // only players use intelligence for critical chance computations
11402  if (Player* modOwner = GetSpellModOwner())
11403  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
11404 
11405  // xinef: can be negative!
11406  return crit_chance;
11407 }
11408 
11409 float Unit::SpellTakenCritChance(Unit const* caster, SpellInfo const* spellProto, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType, bool skipEffectCheck) const
11410 {
11411  // not critting spell
11412  if (spellProto->HasAttribute(SPELL_ATTR2_CANT_CRIT))
11413  return 0.0f;
11414 
11415  // Xinef: check if spell is capable of critting, auras requires special aura to crit so they can be skipped
11416  if (!skipEffectCheck && !spellProto->IsCritCapable())
11417  return 0.0f;
11418 
11419  float crit_chance = doneChance;
11420  switch (spellProto->DmgClass)
11421  {
11423  {
11424  if (!spellProto->IsPositive())
11425  {
11426  // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE
11427  // xinef: apply max and min only
11429  {
11432  }
11433 
11434  Unit::ApplyResilience(this, &crit_chance, nullptr, false, CR_CRIT_TAKEN_SPELL);
11435  }
11436  // scripted (increase crit chance ... against ... target by x%
11437  if (caster)
11438  {
11439  AuraEffectList const& mOverrideClassScript = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
11440  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
11441  {
11442  if (!((*i)->IsAffectedOnSpell(spellProto)))
11443  continue;
11444  int32 modChance = 0;
11445  switch ((*i)->GetMiscValue())
11446  {
11447  // Shatter
11448  case 911:
11449  modChance += 16;
11450  [[fallthrough]];
11451  case 910:
11452  modChance += 17;
11453  [[fallthrough]];
11454  case 849:
11455  modChance += 17;
11456  if (!HasAuraState(AURA_STATE_FROZEN, spellProto, caster))
11457  break;
11458  crit_chance += modChance;
11459  break;
11460  case 7917: // Glyph of Shadowburn
11461  if (HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, caster))
11462  crit_chance += (*i)->GetAmount();
11463  break;
11464  case 7997: // Renewed Hope
11465  case 7998:
11466  if (HasAura(6788))
11467  crit_chance += (*i)->GetAmount();
11468  break;
11469  default:
11470  break;
11471  }
11472  }
11473  // Custom crit by class
11474  switch (spellProto->SpellFamilyName)
11475  {
11476  case SPELLFAMILY_MAGE:
11477  // Glyph of Fire Blast
11478  if (spellProto->SpellFamilyFlags[0] == 0x2 && spellProto->SpellIconID == 12)
11480  if (AuraEffect const* aurEff = caster->GetAuraEffect(56369, EFFECT_0))
11481  crit_chance += aurEff->GetAmount();
11482  break;
11483  case SPELLFAMILY_DRUID:
11484  // Improved Faerie Fire
11486  if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 109, 0))
11487  crit_chance += aurEff->GetAmount();
11488 
11489  // cumulative effect - don't break
11490 
11491  // Starfire
11492  if (spellProto->SpellFamilyFlags[0] & 0x4 && spellProto->SpellIconID == 1485)
11493  {
11494  // Improved Insect Swarm
11495  if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0))
11497  crit_chance += aurEff->GetAmount();
11498  break;
11499  }
11500  break;
11501  case SPELLFAMILY_ROGUE:
11502  // Shiv-applied poisons can't crit
11503  if (caster->FindCurrentSpellBySpellId(5938))
11504  crit_chance = 0.0f;
11505  break;
11506  case SPELLFAMILY_PALADIN:
11507  // Flash of light
11508  if (spellProto->SpellFamilyFlags[0] & 0x40000000)
11509  {
11510  // Sacred Shield
11511  if (AuraEffect const* aura = GetAuraEffect(58597, 1, GetGUID()))
11512  crit_chance += aura->GetAmount();
11513  break;
11514  }
11515  // Exorcism
11516  else if (spellProto->GetCategory() == 19)
11517  {
11519  return 100.0f;
11520  break;
11521  }
11522  break;
11523  case SPELLFAMILY_SHAMAN:
11524  // Lava Burst
11525  if (spellProto->SpellFamilyFlags[1] & 0x00001000)
11526  {
11527  if (GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0, 0, caster->GetGUID()))
11529  return 100.0f;
11530  break;
11531  }
11532  break;
11533  }
11534  }
11535  break;
11536  }
11538  // Custom crit by class
11539  if (caster)
11540  {
11541  switch (spellProto->SpellFamilyName)
11542  {
11543  case SPELLFAMILY_DRUID:
11544  // Rend and Tear - bonus crit chance for Ferocious Bite on bleeding targets
11545  if (spellProto->SpellFamilyFlags[0] & 0x00800000 && spellProto->SpellIconID == 1680 && HasAuraState(AURA_STATE_BLEEDING))
11546  {
11547  if (AuraEffect const* rendAndTear = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 1))
11548  crit_chance += rendAndTear->GetAmount();
11549  break;
11550  }
11551  break;
11552  case SPELLFAMILY_WARRIOR:
11553  // Victory Rush
11554  if (spellProto->SpellFamilyFlags[1] & 0x100)
11555  {
11556  // Glyph of Victory Rush
11557  if (AuraEffect const* aurEff = caster->GetAuraEffect(58382, 0))
11558  crit_chance += aurEff->GetAmount();
11559  break;
11560  }
11561  break;
11562  }
11563  }
11564 
11565  // 100% critical chance against sitting target
11567  {
11568  return 100.0f;
11569  }
11570  [[fallthrough]]; // TODO: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
11572  {
11573  // flat aura mods
11574  if (attackType == RANGED_ATTACK)
11576  else
11578 
11579  // reduce crit chance from Rating for players
11580  if (attackType != RANGED_ATTACK)
11581  {
11582  // xinef: little hack, crit chance dont require caster to calculate, pass victim
11583  Unit::ApplyResilience(this, &crit_chance, nullptr, false, CR_CRIT_TAKEN_MELEE);
11584  }
11585  else
11586  Unit::ApplyResilience(this, &crit_chance, nullptr, false, CR_CRIT_TAKEN_RANGED);
11587 
11588  // Apply crit chance from defence skill
11589  if (caster)
11590  crit_chance += (int32(caster->GetMaxSkillValueForLevel(this)) - int32(GetDefenseSkillValue(caster))) * 0.04f;
11591 
11592  break;
11593  }
11594  // values overridden in spellmgr for lifebloom and earth shield
11596  default:
11597  return 0.0f;
11598  }
11599 
11600  if (caster)
11601  {
11603  for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
11604  {
11605  if (caster->GetGUID() != (*i)->GetCasterGUID())
11606  continue;
11607 
11608  crit_chance += (*i)->GetAmount();
11609  }
11610  }
11611 
11612  // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
11613  // xinef: should be calculated at the end
11614  if (!spellProto->IsPositive())
11616 
11617  // xinef: can be negative!
11618  return crit_chance;
11619 }
11620 
11621 uint32 Unit::SpellCriticalDamageBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit const* victim)
11622 {
11623  // Calculate critical bonus
11624  int32 crit_bonus = damage;
11625  float crit_mod = 0.0f;
11626 
11627  switch (spellProto->DmgClass)
11628  {
11629  case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
11631  // TODO: write here full calculation for melee/ranged spells
11632  crit_bonus += damage;
11633  break;
11634  default:
11635  crit_bonus += damage / 2; // for spells is 50%
11636  break;
11637  }
11638 
11639  if (caster)
11640  {
11642 
11643  if (victim)
11645 
11646  if (crit_bonus != 0 && crit_mod != 0.0f)
11647  AddPct(crit_bonus, crit_mod);
11648 
11649  crit_bonus -= damage;
11650 
11651  if (damage > uint32(crit_bonus))
11652  {
11653  // adds additional damage to critBonus (from talents)
11654  if (Player* modOwner = caster->GetSpellModOwner())
11655  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
11656  }
11657 
11658  crit_bonus += damage;
11659  }
11660 
11661  return crit_bonus;
11662 }
11663 
11664 uint32 Unit::SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit const* victim)
11665 {
11666  // Calculate critical bonus
11667  int32 crit_bonus;
11668  switch (spellProto->DmgClass)
11669  {
11670  case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
11672  // TODO: write here full calculation for melee/ranged spells
11673  crit_bonus = damage;
11674  break;
11675  default:
11676  crit_bonus = damage / 2; // for spells is 50%
11677  break;
11678  }
11679 
11680  if (caster)
11681  {
11682  if (victim)
11683  {
11684  uint32 creatureTypeMask = victim->GetCreatureTypeMask();
11685  crit_bonus = int32(crit_bonus * caster->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
11686  }
11687 
11688  // adds additional damage to critBonus (from talents)
11689  // xinef: used for death knight death coil
11690  if (Player* modOwner = caster->GetSpellModOwner())
11691  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
11692  }
11693 
11694  if (crit_bonus > 0)
11695  damage += crit_bonus;
11696 
11697  if (caster)
11698  damage = int32(float(damage) * caster->GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
11699 
11700  return damage;
11701 }
11702 
11703 float Unit::SpellPctHealingModsDone(Unit* victim, SpellInfo const* spellProto, DamageEffectType damagetype)
11704 {
11705  // For totems get healing bonus from owner (statue isn't totem in fact)
11706  if (GetTypeId() == TYPEID_UNIT && IsTotem())
11707  if (Unit* owner = GetOwner())
11708  return owner->SpellPctHealingModsDone(victim, spellProto, damagetype);
11709 
11710  // Some spells don't benefit from done mods
11712  return 1.0f;
11713 
11714  // xinef: Some spells don't benefit from done mods
11716  return 1.0f;
11717 
11718  // No bonus healing for potion spells
11719  if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
11720  return 1.0f;
11721 
11722  float DoneTotalMod = 1.0f;
11723 
11724  // Healing done percent
11726  for (auto const& auraEff : mHealingDonePct)
11727  {
11728  if (!sScriptMgr->IsNeedModHealPercent(this, auraEff, DoneTotalMod, spellProto))
11729  continue;
11730 
11731  AddPct(DoneTotalMod, auraEff->GetAmount());
11732  }
11733 
11734  // done scripted mod (take it from owner)
11735  Unit* owner = GetOwner() ? GetOwner() : this;
11736  AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
11737  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
11738  {
11739  if (!(*i)->IsAffectedOnSpell(spellProto))
11740  continue;
11741 
11742  switch ((*i)->GetMiscValue())
11743  {
11744  case 21: // Test of Faith
11745  case 6935:
11746  case 6918:
11747  if (victim->HealthBelowPct(50))
11748  AddPct(DoneTotalMod, (*i)->GetAmount());
11749  break;
11750  case 7798: // Glyph of Regrowth
11751  {
11752  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0))
11753  AddPct(DoneTotalMod, (*i)->GetAmount());
11754  break;
11755  }
11756 
11757  case 7871: // Glyph of Lesser Healing Wave
11758  {
11759  // xinef: affected by any earth shield
11760  if (victim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0, 0x00000400, 0))
11761  AddPct(DoneTotalMod, (*i)->GetAmount());
11762  break;
11763  }
11764  default:
11765  break;
11766  }
11767  }
11768 
11769  switch (spellProto->SpellFamilyName)
11770  {
11771  case SPELLFAMILY_GENERIC:
11772  // Talents and glyphs for healing stream totem
11773  if (spellProto->Id == 52042)
11774  {
11775  // Glyph of Healing Stream Totem
11776  if (AuraEffect* dummy = owner->GetAuraEffect(55456, EFFECT_0))
11777  AddPct(DoneTotalMod, dummy->GetAmount());
11778 
11779  // Healing Stream totem - Restorative Totems
11780  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 338, 1))
11781  AddPct(DoneTotalMod, aurEff->GetAmount());
11782  }
11783  break;
11784  case SPELLFAMILY_PRIEST:
11785  // T9 HEALING 4P, empowered renew instant heal
11786  if (spellProto->Id == 63544)
11787  if (AuraEffect* aurEff = GetAuraEffect(67202, EFFECT_0))
11788  AddPct(DoneTotalMod, aurEff->GetAmount());
11789  break;
11790  }
11791 
11792  return DoneTotalMod;
11793 }
11794 
11795 uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, float TotalMod, uint32 stack)
11796 {
11797  // For totems get healing bonus from owner (statue isn't totem in fact)
11798  if (GetTypeId() == TYPEID_UNIT && IsTotem())
11799  if (Unit* owner = GetOwner())
11800  return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, TotalMod, stack);
11801 
11802  // No bonus healing for potion spells
11803  if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
11804  return healamount;
11805 
11806  float ApCoeffMod = 1.0f;
11807  float DoneTotalMod = TotalMod ? TotalMod : SpellPctHealingModsDone(victim, spellProto, damagetype);
11808  int32 DoneTotal = 0;
11809 
11810  // done scripted mod (take it from owner)
11811  Unit* owner = GetOwner() ? GetOwner() : this;
11812  AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
11813  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
11814  {
11815  if (!(*i)->IsAffectedOnSpell(spellProto))
11816  continue;
11817  switch ((*i)->GetMiscValue())
11818  {
11819  case 4415: // Increased Rejuvenation Healing
11820  case 4953:
11821  case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
11822  DoneTotal += (*i)->GetAmount();
11823  break;
11824  }
11825  }
11826 
11827  // Done fixed damage bonus auras
11828  int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
11829  float coeff = 0;
11830 
11831  switch (spellProto->SpellFamilyName)
11832  {
11834  // Impurity
11835  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 1986, 0))
11836  AddPct(ApCoeffMod, aurEff->GetAmount());
11837 
11838  break;
11839  }
11840 
11841  // Check for table values
11842  SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
11843  if(bonus)
11844  {
11845  if (damagetype == DOT)
11846  {
11847  coeff = bonus->dot_damage;
11848  if (bonus->ap_dot_bonus > 0)
11849  DoneTotal += int32(bonus->ap_dot_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
11850  (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
11851  }
11852  else
11853  {
11854  coeff = bonus->direct_damage;
11855  if (bonus->ap_bonus > 0)
11856  DoneTotal += int32(bonus->ap_bonus * ApCoeffMod * stack * GetTotalAttackPowerValue(
11857  (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
11858  }
11859  }
11860  else
11861  {
11862  // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
11863  if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
11864  return healamount;
11865  }
11866 
11867  // Default calculation
11868  if (DoneAdvertisedBenefit)
11869  {
11870  float factorMod = CalculateLevelPenalty(spellProto) * stack;
11871  if (Player* modOwner = GetSpellModOwner())
11872  {
11873  coeff *= 100.0f;
11874  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
11875  coeff /= 100.0f;
11876  }
11877  DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
11878  }
11879 
11880  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
11881  {
11882  switch (spellProto->Effects[i].ApplyAuraName)
11883  {
11884  // Bonus healing does not apply to these spells
11887  DoneTotal = 0;
11888  break;
11889  }
11890  if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
11891  DoneTotal = 0;
11892  }
11893 
11894  // use float as more appropriate for negative values and percent applying
11895  float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod;
11896  // apply spellmod to Done amount
11897 
11898  if (Player* modOwner = GetSpellModOwner())
11899  modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
11900 
11901  return uint32(std::max(heal, 0.0f));
11902 }
11903 
11904 uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
11905 {
11906  float TakenTotalMod = 1.0f;
11907 
11908  // Healing taken percent
11910  if (minval)
11911  AddPct(TakenTotalMod, minval);
11912 
11914  if (maxval)
11915  AddPct(TakenTotalMod, maxval);
11916 
11917  // Tenacity increase healing % taken
11918  if (AuraEffect const* Tenacity = GetAuraEffect(58549, 0))
11919  AddPct(TakenTotalMod, Tenacity->GetAmount());
11920 
11921  // Healing Done
11922  int32 TakenTotal = 0;
11923 
11924  // Taken fixed damage bonus auras
11925  int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask());
11926 
11927  // Nourish cast, glyph of nourish
11928  if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000 && caster)
11929  {
11930  bool any = false;
11931  bool hasglyph = caster->GetAuraEffectDummy(62971);
11933  for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
11934  {
11935  if (((*i)->GetCasterGUID() == caster->GetGUID()))
11936  {
11937  SpellInfo const* spell = (*i)->GetSpellInfo();
11938  // Rejuvenation, Regrowth, Lifebloom, or Wild Growth
11939  if (!any && spell->SpellFamilyFlags.HasFlag(0x50, 0x4000010, 0))
11940  {
11941  TakenTotalMod *= 1.2f;
11942  any = true;
11943  }
11944 
11945  if (hasglyph)
11946  TakenTotalMod += 0.06f;
11947  }
11948  }
11949  }
11950 
11951  if (damagetype == DOT)
11952  {
11953  // Healing over time taken percent
11954  float minval_hot = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT));
11955  if (minval_hot)
11956  AddPct(TakenTotalMod, minval_hot);
11957 
11958  float maxval_hot = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT));
11959  if (maxval_hot)
11960  AddPct(TakenTotalMod, maxval_hot);
11961  }
11962 
11963  // Check for table values
11964  SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
11965  float coeff = 0;
11966  float factorMod = 1.0f;
11967  if (bonus)
11968  coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
11969  else
11970  {
11971  // No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
11972  if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
11973  {
11974  healamount = uint32(std::max((float(healamount) * TakenTotalMod), 0.0f));
11975  return healamount;
11976  }
11977  }
11978 
11979  // Default calculation
11980  if (TakenAdvertisedBenefit)
11981  {
11982  float TakenCoeff = 0.0f;
11983  if (coeff <= 0)
11984  coeff = CalculateDefaultCoefficient(spellProto, damagetype) * int32(stack) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells)
11985 
11986  factorMod *= CalculateLevelPenalty(spellProto) * int32(stack);
11987  if (Player* modOwner = GetSpellModOwner())
11988  {
11989  coeff *= 100.0f;
11990  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_BONUS_MULTIPLIER, coeff);
11991  coeff /= 100.0f;
11992  }
11993 
11994  TakenTotal += int32(TakenAdvertisedBenefit * (coeff > 0 ? coeff : TakenCoeff) * factorMod);
11995  }
11996 
11997  if (caster)
11998  {
11999  AuraEffectList const& mHealingGet = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED);
12000  for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
12001  if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto))
12002  AddPct(TakenTotalMod, (*i)->GetAmount());
12003  }
12004 
12005  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
12006  {
12007  switch (spellProto->Effects[i].ApplyAuraName)
12008  {
12009  // Bonus healing does not apply to these spells
12012  TakenTotal = 0;
12013  break;
12014  }
12015  if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
12016  TakenTotal = 0;
12017  }
12018 
12019  // No positive taken bonus, custom attr
12020  if ((spellProto->HasAttribute(SPELL_ATTR6_IGNORE_HEALTH_MODIFIERS) || spellProto->HasAttribute(SPELL_ATTR0_CU_NO_POSITIVE_TAKEN_BONUS)) && TakenTotalMod > 1.0f)
12021  {
12022  TakenTotal = 0;
12023  TakenTotalMod = 1.0f;
12024  }
12025 
12026  float heal = float(int32(healamount) + TakenTotal) * TakenTotalMod;
12027 
12028  return uint32(std::max(heal, 0.0f));
12029 }
12030 
12032 {
12033  int32 AdvertisedBenefit = 0;
12034 
12036  for (AuraEffectList::const_iterator i = mHealingDone.begin(); i != mHealingDone.end(); ++i)
12037  if (!(*i)->GetMiscValue() || ((*i)->GetMiscValue() & schoolMask) != 0)
12038  AdvertisedBenefit += (*i)->GetAmount();
12039 
12040  // Healing bonus of spirit, intellect and strength
12041  if (GetTypeId() == TYPEID_PLAYER)
12042  {
12043  // Base value
12044  AdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus();
12045 
12046  // Healing bonus from stats
12048  for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i)
12049  {
12050  // stat used dependent from misc value (stat index)
12051  Stats usedStat = Stats((*i)->GetSpellInfo()->Effects[(*i)->GetEffIndex()].MiscValue);
12052  AdvertisedBenefit += int32(CalculatePct(GetStat(usedStat), (*i)->GetAmount()));
12053  }
12054 
12055  // ... and attack power
12057  for (AuraEffectList::const_iterator i = mHealingDonebyAP.begin(); i != mHealingDonebyAP.end(); ++i)
12058  if ((*i)->GetMiscValue() & schoolMask)
12059  AdvertisedBenefit += int32(CalculatePct(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount()));
12060  }
12061  return AdvertisedBenefit;
12062 }
12063 
12065 {
12066  int32 AdvertisedBenefit = 0;
12067 
12069  for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
12070  if (((*i)->GetMiscValue() & schoolMask) != 0)
12071  AdvertisedBenefit += (*i)->GetAmount();
12072 
12073  return AdvertisedBenefit;
12074 }
12075 
12076 bool Unit::IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
12077 {
12078  // If m_immuneToDamage type contain magic, IMMUNE damage.
12079  SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
12080  for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
12081  if((itr->type & meleeSchoolMask) == meleeSchoolMask)
12082  return true;
12083 
12084  return false;
12085 }
12086 
12087 bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
12088 {
12089  if (!spellInfo)
12090  {
12091  return false;
12092  }
12093 
12095  {
12096  return false;
12097  }
12098 
12100  {
12101  return false;
12102  }
12103 
12104  uint32 schoolMask = spellInfo->GetSchoolMask();
12105  // If m_immuneToDamage type contain magic, IMMUNE damage.
12106  SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
12107  for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
12108  if((itr->type & schoolMask) == schoolMask)
12109  return true;
12110 
12111  return false;
12112 }
12113 
12114 bool Unit::IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const
12115 {
12116  // If m_immuneToSchool type contain this school type, IMMUNE damage.
12117  SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
12118  for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
12119  if((itr->type & meleeSchoolMask) == meleeSchoolMask)
12120  return true;
12121 
12122  return false;
12123 }
12124 
12125 bool Unit::IsImmunedToSchool(SpellInfo const* spellInfo) const
12126 {
12128  return false;
12129 
12130  uint32 schoolMask = spellInfo->GetSchoolMask();
12131  if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
12132  {
12133  // If m_immuneToSchool type contain this school type, IMMUNE damage.
12134  SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
12135  for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
12136  if((itr->type & schoolMask) == schoolMask && !spellInfo->CanPierceImmuneAura(sSpellMgr->GetSpellInfo(itr->spellId)))
12137  return true;
12138  }
12139 
12140  return false;
12141 }
12142 
12144 {
12145  return IsImmunedToDamage(meleeSchoolMask) || IsImmunedToSchool(meleeSchoolMask);
12146 }
12147 
12148 bool Unit::IsImmunedToDamageOrSchool(SpellInfo const* spellInfo) const
12149 {
12150  return IsImmunedToDamage(spellInfo) || IsImmunedToSchool(spellInfo);
12151 }
12152 
12153 bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
12154 {
12155  if (!spellInfo)
12156  return false;
12157 
12158  // Single spell immunity.
12159  SpellImmuneList const& idList = m_spellImmune[IMMUNITY_ID];
12160  for (SpellImmuneList::const_iterator itr = idList.begin(); itr != idList.end(); ++itr)
12161  if (itr->type == spellInfo->Id)
12162  return true;
12163 
12164  // xinef: my special immunity, if spellid is not on this list it means npc is immune
12165  SpellImmuneList const& allowIdList = m_spellImmune[IMMUNITY_ALLOW_ID];
12166  if (!allowIdList.empty())
12167  {
12168  for (SpellImmuneList::const_iterator itr = allowIdList.begin(); itr != allowIdList.end(); ++itr)
12169  if (itr->type == spellInfo->Id)
12170  return false;
12171  return true;
12172  }
12173 
12175  return false;
12176 
12177  if (spellInfo->Dispel)
12178  {
12179  SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
12180  for (SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
12181  if (itr->type == spellInfo->Dispel)
12182  return true;
12183  }
12184 
12185  // Spells that don't have effectMechanics.
12186  if (spellInfo->Mechanic)
12187  {
12188  SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
12189  for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
12190  if (itr->type == spellInfo->Mechanic)
12191  return true;
12192  }
12193 
12194  bool immuneToAllEffects = true;
12195  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
12196  {
12197  // State/effect immunities applied by aura expect full spell immunity
12198  // Ignore effects with mechanic, they are supposed to be checked separately
12199  if (!spellInfo->Effects[i].IsEffect())
12200  continue;
12201 
12202  // Xinef: if target is immune to one effect, and the spell has transform aura - it is immune to whole spell
12203  if (IsImmunedToSpellEffect(spellInfo, i))
12204  {
12205  if (spellInfo->HasAura(SPELL_AURA_TRANSFORM))
12206  return true;
12207  continue;
12208  }
12209 
12210  immuneToAllEffects = false;
12211  break;
12212  }
12213  if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
12214  return true;
12215 
12216  if (spellInfo->Id != 42292 && spellInfo->Id != 59752 && spellInfo->Id != 19574 && spellInfo->Id != 34471)
12217  {
12218  SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
12219  for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
12220  {
12221  SpellInfo const* immuneSpellInfo = sSpellMgr->GetSpellInfo(itr->spellId);
12222  if (((itr->type & spellInfo->GetSchoolMask()) == spellInfo->GetSchoolMask())
12223  && !(immuneSpellInfo && immuneSpellInfo->IsPositive()) && !spellInfo->IsPositive()
12224  && !spellInfo->CanPierceImmuneAura(immuneSpellInfo))
12225  return true;
12226  }
12227  }
12228 
12229  return false;
12230 }
12231 
12232 bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
12233 {
12234  if (!spellInfo || !spellInfo->Effects[index].IsEffect())
12235  return false;
12236 
12237  // xinef: pet scaling auras
12239  return false;
12240 
12242  return false;
12243 
12244  //If m_immuneToEffect type contain this effect type, IMMUNE effect.
12245  uint32 effect = spellInfo->Effects[index].Effect;
12246  SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
12247  for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
12248  if (itr->type == effect && (itr->spellId != 62692 || spellInfo->Effects[index].MiscValue == POWER_MANA))
12249  return true;
12250 
12251  if (uint32 mechanic = spellInfo->Effects[index].Mechanic)
12252  {
12253  SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
12254  for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
12255  if (itr->type == mechanic)
12256  return true;
12257  }
12258 
12259  if (uint32 aura = spellInfo->Effects[index].ApplyAuraName)
12260  {
12262  for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
12263  if (itr->type == aura && (itr->spellId != 64848 || spellInfo->Effects[index].MiscValue == POWER_MANA))
12264  if (!spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
12265  if (itr->blockType == SPELL_BLOCK_TYPE_ALL || spellInfo->IsPositive()) // xinef: added for pet scaling
12266  return true;
12267 
12269  {
12270  // Check for immune to application of harmful magical effects
12272  for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
12273  {
12274  if (/*(spellInfo->Dispel == DISPEL_MAGIC || spellInfo->Dispel == DISPEL_CURSE || spellInfo->Dispel == DISPEL_DISEASE) &&*/ // Magic debuff, xinef: all kinds?
12275  ((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
12276  !spellInfo->IsPositiveEffect(index) && // Harmful
12277  spellInfo->Effects[index].Effect != SPELL_EFFECT_PERSISTENT_AREA_AURA) // Not Persistent area auras
12278  {
12279  return true;
12280  }
12281  }
12282  }
12283  }
12284 
12285  return false;
12286 }
12287 
12288 uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
12289 {
12290  if (!victim || pdamage == 0)
12291  return 0;
12292 
12293  if (GetTypeId() == TYPEID_UNIT)
12294  {
12295  // Dancing Rune Weapon...
12296  if (GetEntry() == 27893)
12297  {
12298  if (Unit* owner = GetOwner())
12299  return owner->MeleeDamageBonusDone(victim, pdamage, attType, spellProto) / 2;
12300  }
12301  }
12302 
12303  uint32 creatureTypeMask = victim->GetCreatureTypeMask();
12304 
12305  // Done fixed damage bonus auras
12306  int32 DoneFlatBenefit = 0;
12307 
12308  // ..done
12310  for (AuraEffectList::const_iterator i = mDamageDoneCreature.begin(); i != mDamageDoneCreature.end(); ++i)
12311  if (creatureTypeMask & uint32((*i)->GetMiscValue()))
12312  DoneFlatBenefit += (*i)->GetAmount();
12313 
12314  // ..done
12315  // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage
12316 
12317  // ..done (base at attack power for marked target and base at attack power for creature type)
12318  int32 APbonus = 0;
12319 
12320  if (attType == RANGED_ATTACK)
12321  {
12323 
12324  // ..done (base at attack power and creature type)
12326  for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i)
12327  if (creatureTypeMask & uint32((*i)->GetMiscValue()))
12328  APbonus += (*i)->GetAmount();
12329  }
12330  else
12331  {
12333 
12334  // ..done (base at attack power and creature type)
12336  for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i)
12337  if (creatureTypeMask & uint32((*i)->GetMiscValue()))
12338  APbonus += (*i)->GetAmount();
12339  }
12340 
12341  if (APbonus != 0) // Can be negative
12342  {
12343  bool normalized = false;
12344  if (spellProto)
12345  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
12346  if (spellProto->Effects[i].Effect == SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
12347  {
12348  normalized = true;
12349  break;
12350  }
12351  DoneFlatBenefit += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized));
12352  }
12353 
12354  // Done total percent damage auras
12355  float DoneTotalMod = 1.0f;
12356 
12357  // Some spells don't benefit from pct done mods
12358  if (spellProto)
12359  {
12361  for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
12362  {
12363  if (!spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
12364  continue;
12365 
12366  if (!sScriptMgr->IsNeedModMeleeDamagePercent(this, *i, DoneTotalMod, spellProto))
12367  continue;
12368 
12369  if (((*i)->GetMiscValue() & spellProto->GetSchoolMask()) && !((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
12370  {
12371  if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
12372  AddPct(DoneTotalMod, (*i)->GetAmount());
12373  else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPED_ITEM) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
12374  AddPct(DoneTotalMod, (*i)->GetAmount());
12375  else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
12376  AddPct(DoneTotalMod, (*i)->GetAmount());
12377  }
12378  }
12379  }
12380 
12382  for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
12383  if (creatureTypeMask & uint32((*i)->GetMiscValue()))
12384  if (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
12385  AddPct(DoneTotalMod, (*i)->GetAmount());
12386 
12387  // bonus against aurastate
12389  for (AuraEffectList::const_iterator i = mDamageDoneVersusAurastate.begin(); i != mDamageDoneVersusAurastate.end(); ++i)
12390  if (victim->HasAuraState(AuraStateType((*i)->GetMiscValue())))
12391  if (!spellProto || spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
12392  AddPct(DoneTotalMod, (*i)->GetAmount());
12393 
12394  // done scripted mod (take it from owner)
12395  Unit* owner = GetOwner() ? GetOwner() : this;
12396  AuraEffectList const& mOverrideClassScript = owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
12397  for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
12398  {
12399  if (spellProto && !spellProto->ValidateAttribute6SpellDamageMods(this, *i, false))
12400  continue;
12401 
12402  if (!(*i)->IsAffectedOnSpell(spellProto))
12403  continue;
12404 
12405  switch ((*i)->GetMiscValue())
12406  {
12407  // Tundra Stalker
12408  // Merciless Combat
12409  case 7277:
12410  {
12411  // Merciless Combat
12412  if ((*i)->GetSpellInfo()->SpellIconID == 2656)
12413  {
12414  if (!victim->HealthAbovePct(35))
12415  AddPct(DoneTotalMod, (*i)->GetAmount());
12416  }
12417  // Tundra Stalker
12418  else
12419  {
12420  // Frost Fever (target debuff)
12421  if (victim->HasAura(55095))
12422  AddPct(DoneTotalMod, (*i)->GetAmount());
12423  }
12424  break;
12425  }
12426  // Rage of Rivendare
12427  case 7293:
12428  {
12429  if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0x02000000, 0))
12430  AddPct(DoneTotalMod, (*i)->GetSpellInfo()->GetRank() * 2.0f);
12431  break;
12432  }
12433  // Marked for Death
12434  case 7598:
12435  case 7599:
12436  case 7600:
12437  case 7601:
12438  case 7602:
12439  {
12440  if (victim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0))
12441  AddPct(DoneTotalMod, (*i)->GetAmount());
12442  break;
12443  }
12444  // Dirty Deeds
12445  case 6427:
12446  case 6428:
12447  {
12448  if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this))
12449  {
12450  // effect 0 has expected value but in negative state
12451  int32 bonus = -(*i)->GetBase()->GetEffect(0)->GetAmount();
12452  AddPct(DoneTotalMod, bonus);
12453  }
12454  break;
12455  }
12456  }
12457  }
12458 
12459  // Custom scripted damage
12460  if (spellProto)
12461  switch (spellProto->SpellFamilyName)
12462  {
12464  // Glacier Rot
12465  if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6)
12466  if (AuraEffect* aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0))
12467  if (victim->GetDiseasesByCaster(owner->GetGUID()) > 0)
12468  AddPct(DoneTotalMod, aurEff->GetAmount());
12469  break;
12470  }
12471 
12472  // Some spells don't benefit from done mods
12473  if (spellProto)
12475  {
12476  DoneFlatBenefit = 0;
12477  DoneTotalMod = 1.0f;
12478  }
12479 
12480  float tmpDamage = float(int32(pdamage) + DoneFlatBenefit) * DoneTotalMod;
12481 
12482  // apply spellmod to Done damage
12483  if (spellProto)
12484  if (Player* modOwner = GetSpellModOwner())
12485  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
12486 
12487  // bonus result can be negative
12488  return uint32(std::max(tmpDamage, 0.0f));
12489 }
12490 
12491 uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
12492 {
12493  if (pdamage == 0)
12494  return 0;
12495 
12496  int32 TakenFlatBenefit = 0;
12497 
12498  // ..taken
12500  for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i)
12501  if ((*i)->GetMiscValue() & (spellProto ? spellProto->GetSchoolMask() : attacker->GetMeleeDamageSchoolMask()))
12502  TakenFlatBenefit += (*i)->GetAmount();
12503 
12504  if (attType != RANGED_ATTACK)
12506  else
12508 
12509  // Taken total percent damage auras
12510  float TakenTotalMod = 1.0f;
12511 
12512  TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto ? spellProto->GetSchoolMask() : attacker->GetMeleeDamageSchoolMask());
12513 
12514  // .. taken pct (special attacks)
12515  if (spellProto)
12516  {
12517  // From caster spells
12519  for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
12520  if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
12521  AddPct(TakenTotalMod, (*i)->GetAmount());
12522 
12523  // Mod damage from spell mechanic
12524  uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask();
12525 
12526  // Shred, Maul - "Effects which increase Bleed damage also increase Shred damage"
12527  if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[0] & 0x00008800)
12528  mechanicMask |= (1 << MECHANIC_BLEED);
12529 
12530  if (mechanicMask)
12531  {
12533  for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i)
12534  if (mechanicMask & uint32(1 << ((*i)->GetMiscValue())))
12535  AddPct(TakenTotalMod, (*i)->GetAmount());
12536  }
12537  }
12538 
12539  TakenTotalMod = processDummyAuras(TakenTotalMod);
12540 
12541  // .. taken pct: class scripts
12542  /*AuraEffectList const& mclassScritAuras = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
12543  for (AuraEffectList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i)
12544  {
12545  switch ((*i)->GetMiscValue())
12546  {
12547  }
12548  }*/
12549 
12550  if (attType != RANGED_ATTACK)
12551  {
12552  AuraEffectList const& mModMeleeDamageTakenPercent = GetAuraEffectsByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
12553  for (AuraEffectList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i)
12554  AddPct(TakenTotalMod, (*i)->GetAmount());
12555  }
12556  else
12557  {
12558  AuraEffectList const& mModRangedDamageTakenPercent = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
12559  for (AuraEffectList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i)
12560  AddPct(TakenTotalMod, (*i)->GetAmount());
12561  }
12562 
12563  // No positive taken bonus, custom attr
12564  if (spellProto)
12565  if (spellProto->HasAttribute(SPELL_ATTR0_CU_NO_POSITIVE_TAKEN_BONUS) && TakenTotalMod > 1.0f)
12566  {
12567  TakenFlatBenefit = 0;
12568  TakenTotalMod = 1.0f;
12569  }
12570 
12571  // xinef: sanctified wrath talent
12572  if (TakenTotalMod < 1.0f && attacker->HasAuraType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST))
12573  {
12574  float ignoreModifier = 1.0f - TakenTotalMod;
12575  bool addModifier = false;
12576  AuraEffectList const& ResIgnoreAuras = attacker->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
12577  for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j)
12578  if ((*j)->GetMiscValue() & (spellProto ? spellProto->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL))
12579  {
12580  ApplyPct(ignoreModifier, (*j)->GetAmount());
12581  addModifier = true;
12582  }
12583 
12584  if (addModifier)
12585  TakenTotalMod += ignoreModifier;
12586  }
12587 
12588  float tmpDamage = (float(pdamage) + TakenFlatBenefit) * TakenTotalMod;
12589 
12590  // bonus result can be negative
12591  return uint32(std::max(tmpDamage, 0.0f));
12592 }
12593 
12595 {
12596 public:
12598  bool operator()(SpellImmune const& spellImmune) { return spellImmune.spellId == 0 && spellImmune.type == _type; }
12599 
12600 private:
12602 };
12603 
12605 {
12606  if (apply)
12607  {
12608  // xinef: immunities with spellId 0 are intended to be applied only once (script purposes mosty)
12609  if (spellId == 0 && std::find_if(m_spellImmune[op].begin(), m_spellImmune[op].end(), spellIdImmunityPredicate(type)) != m_spellImmune[op].end())
12610  return;
12611 
12612  SpellImmune immune;
12613  immune.spellId = spellId;
12614  immune.type = type;
12615  immune.blockType = blockType;
12616  m_spellImmune[op].push_back(std::move(immune));
12617  }
12618  else
12619  {
12620  for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr)
12621  {
12622  if (itr->spellId == spellId && itr->type == type)
12623  {
12624  m_spellImmune[op].erase(itr);
12625  break;
12626  }
12627  }
12628  }
12629 }
12630 
12632 {
12633  ApplySpellImmune(spellProto->Id, IMMUNITY_DISPEL, type, apply);
12634 
12636  {
12637  // Create dispel mask by dispel type
12638  uint32 dispelMask = SpellInfo::GetDispelMask(type);
12639  // Dispel all existing auras vs current dispel type
12641  for (AuraApplicationMap::iterator itr = auras.begin(); itr != auras.end();)
12642  {
12643  SpellInfo const* spell = itr->second->GetBase()->GetSpellInfo();
12644  if (spell->GetDispelMask() & dispelMask)
12645  {
12646  // Dispel aura
12647  RemoveAura(itr);
12648  }
12649  else
12650  ++itr;
12651  }
12652  }
12653 }
12654 
12656 {
12657  // normalized proc chance for weapon attack speed
12658  // (odd formula...)
12660  return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f);
12662  return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f);
12663  return 0;
12664 }
12665 
12666 float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spellProto) const
12667 {
12668  // proc per minute chance calculation
12669  if (PPM <= 0)
12670  return 0.0f;
12671 
12672  // Apply chance modifer aura
12673  if (spellProto)
12674  if (Player* modOwner = GetSpellModOwner())
12675  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_PROC_PER_MINUTE, PPM);
12676 
12677  return floor((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
12678 }
12679 
12680 void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
12681 {
12682  if (mount)
12684 
12686 
12687  if (Player* player = ToPlayer())
12688  {
12689  sScriptMgr->AnticheatSetUnderACKmount(player);
12690 
12691  // mount as a vehicle
12692  if (VehicleId)
12693  {
12694  if (CreateVehicleKit(VehicleId, creatureEntry))
12695  {
12696  GetVehicleKit()->Reset();
12697 
12698  // Send others that we now have a vehicle
12700  data << GetPackGUID();
12701  data << uint32(VehicleId);
12702  SendMessageToSet(&data, true);
12703 
12705  player->GetSession()->SendPacket(&data);
12706 
12707  // mounts can also have accessories
12709  }
12710  }
12711 
12712  // unsummon pet
12713  Pet* pet = player->GetPet();
12714  if (pet)
12715  {
12717  // don't unsummon pet in arena but SetFlag UNIT_FLAG_STUNNED to disable pet's interface
12718  if (bg && bg->isArena())
12720  else
12721  player->UnsummonPetTemporaryIfAny();
12722  }
12723 
12724  // xinef: if we have charmed npc, stun him also
12725  if (Unit* charm = player->GetCharm())
12726  if (charm->GetTypeId() == TYPEID_UNIT)
12727  charm->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
12728 
12730  data << GetPackGUID();
12731  data << uint32(sWorld->GetGameTime()); // Packet counter
12732  data << player->GetCollisionHeight();
12733  player->GetSession()->SendPacket(&data);
12734  }
12735 
12737 }
12738 
12740 {
12741  if (!IsMounted())
12742  return;
12743 
12746 
12747  if (Player* thisPlayer = ToPlayer())
12748  {
12750  data << GetPackGUID();
12751  data << uint32(sWorld->GetGameTime()); // Packet counter
12752  data << thisPlayer->GetCollisionHeight();
12753  thisPlayer->GetSession()->SendPacket(&data);
12754  }
12755 
12757  data << GetPackGUID();
12758  SendMessageToSet(&data, true);
12759 
12760  // dismount as a vehicle
12761  if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
12762  {
12763  // Send other players that we are no longer a vehicle
12764  data.Initialize(SMSG_PLAYER_VEHICLE_DATA, 8 + 4);
12765  data << GetPackGUID();
12766  data << uint32(0);
12767  ToPlayer()->SendMessageToSet(&data, true);
12768  // Remove vehicle from player
12769  RemoveVehicleKit();
12770  }
12771 
12773 
12774  // only resummon old pet if the player is already added to a map
12775  // this prevents adding a pet to a not created map which would otherwise cause a crash
12776  // (it could probably happen when logging in after a previous crash)
12777  if (Player* player = ToPlayer())
12778  {
12779  sScriptMgr->AnticheatSetUnderACKmount(player);
12780 
12781  if (Pet* pPet = player->GetPet())
12782  {
12783  if (pPet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED) && !pPet->HasUnitState(UNIT_STATE_STUNNED))
12784  pPet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
12785  }
12786  else
12787  player->ResummonPetTemporaryUnSummonedIfAny();
12788 
12789  // xinef: if we have charmed npc, remove stun also
12790  if (Unit* charm = player->GetCharm())
12791  if (charm->GetTypeId() == TYPEID_UNIT && !charm->HasUnitState(UNIT_STATE_STUNNED))
12792  charm->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
12793  }
12794 }
12795 
12796 void Unit::SetInCombatWith(Unit* enemy, uint32 duration)
12797 {
12798  // Xinef: Dont allow to start combat with triggers
12799  if (enemy->GetTypeId() == TYPEID_UNIT && enemy->ToCreature()->IsTrigger())
12800  return;
12801 
12802  Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf();
12803  if (eOwner->IsPvP() || eOwner->IsFFAPvP())
12804  {
12805  SetInCombatState(true, enemy, duration);
12806  return;
12807  }
12808 
12809  // check for duel
12810  if (eOwner->GetTypeId() == TYPEID_PLAYER && eOwner->ToPlayer()->duel)
12811  {
12812  Unit const* myOwner = GetCharmerOrOwnerOrSelf();
12813  if (((Player const*)eOwner)->duel->opponent == myOwner)
12814  {
12815  SetInCombatState(true, enemy, duration);
12816  return;
12817  }
12818  }
12819  SetInCombatState(false, enemy, duration);
12820 }
12821 
12822 void Unit::CombatStart(Unit* victim, bool initialAggro)
12823 {
12824  // Xinef: Dont allow to start combat with triggers
12825  if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsTrigger())
12826  return;
12827 
12828  if (initialAggro)
12829  {
12830  // Make player victim stand up automatically
12831  if (victim->getStandState() && victim->IsPlayer())
12832  {
12834  }
12835 
12836  if (!victim->IsInCombat() && victim->GetTypeId() != TYPEID_PLAYER && !victim->ToCreature()->HasReactState(REACT_PASSIVE) && victim->ToCreature()->IsAIEnabled)
12837  {
12838  if (victim->IsPet())
12839  victim->ToCreature()->AI()->AttackedBy(this); // PetAI has special handler before AttackStart()
12840  else
12841  {
12842  victim->ToCreature()->AI()->AttackStart(this);
12843  // if the target is an NPC with a pet or minion, pet should react.
12844  if (Unit* victimControlledUnit = victim->GetFirstControlled())
12845  {
12846  victimControlledUnit->SetInCombatWith(this);
12847  SetInCombatWith(victimControlledUnit);
12848  victimControlledUnit->AddThreat(this, 0.0f);
12849  }
12850  }
12851 
12852  // if unit has an owner, put owner in combat.
12853  if (Unit* victimOwner = victim->GetOwner())
12854  {
12855  if (!(victimOwner->IsInCombatWith(this)))
12856  {
12857  /* warding off to not take over aggro for no reason
12858  Using only AddThreat causes delay in attack */
12859  if (!victimOwner->IsInCombat() && victimOwner->IsAIEnabled)
12860  {
12861  victimOwner->ToCreature()->AI()->AttackStart(this);
12862  }
12863  victimOwner->SetInCombatWith(this);
12864  SetInCombatWith(victimOwner);
12865  victimOwner->AddThreat(this, 0.0f);
12866  }
12867  }
12868  }
12869 
12870  SetInCombatWith(victim);
12871  victim->SetInCombatWith(this);
12872 
12873  // Xinef: If pet started combat - put owner in combat
12874  if (Unit* owner = GetOwner())
12875  {
12876  owner->SetInCombatWith(victim);
12877  victim->SetInCombatWith(owner);
12878  }
12879  }
12880 
12881  Unit* who = victim->GetCharmerOrOwnerOrSelf();
12882  if (who->GetTypeId() == TYPEID_PLAYER)
12883  SetContestedPvP(who->ToPlayer());
12884 
12886  if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->opponent != who))
12887  {
12888  me->UpdatePvP(true);
12890  }
12891 }
12892 
12893 void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration)
12894 {
12895  // Xinef: Dont allow to start combat with triggers
12896  if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->IsTrigger())
12897  return;
12898 
12899  if (initialAggro)
12900  {
12901  SetInCombatWith(target, duration);
12902 
12903  // Xinef: If pet started combat - put owner in combat
12904  if (Unit* owner = GetOwner())
12905  owner->SetInCombatWith(target, duration);
12906  }
12907 
12908  Unit* who = target->GetCharmerOrOwnerOrSelf();
12909  if (who->GetTypeId() == TYPEID_PLAYER)
12910  SetContestedPvP(who->ToPlayer());
12911 
12913  if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->opponent != who))
12914  {
12915  me->UpdatePvP(true);
12917  }
12918 }
12919 
12920 void Unit::SetInCombatState(bool PvP, Unit* enemy, uint32 duration)
12921 {
12922  // only alive units can be in combat
12923  if (!IsAlive())
12924  return;
12925 
12926  if (PvP)
12927  m_CombatTimer = std::max<uint32>(GetCombatTimer(), std::max<uint32>(5500, duration));
12928  else if (duration)
12929  m_CombatTimer = std::max<uint32>(GetCombatTimer(), duration);
12930 
12932  return;
12933 
12934  // xinef: if we somehow engage in combat (scripts, dunno) with player, remove this flag so he can fight back
12936  RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // unit has engaged in combat, remove immunity so players can fight back
12937 
12938  if (IsInCombat())
12939  return;
12940 
12942 
12943  if (Creature* creature = ToCreature())
12944  {
12945  // Set home position at place of engaging combat for escorted creatures
12946  if ((IsAIEnabled && creature->AI()->IsEscorted()) ||
12947  GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE ||
12948  GetMotionMaster()->GetCurrentMovementGeneratorType() == ESCORT_MOTION_TYPE)
12949  creature->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
12950 
12951  if (enemy)
12952  {
12953  if (IsAIEnabled)
12954  creature->AI()->EnterCombat(enemy);
12955 
12956  if (creature->GetFormation())
12957  creature->GetFormation()->MemberAttackStart(creature, enemy);
12958  }
12959 
12960  creature->RefreshSwimmingFlag();
12961 
12962  if (IsPet())
12963  {
12964  UpdateSpeed(MOVE_RUN, true);
12965  UpdateSpeed(MOVE_SWIM, true);
12966  UpdateSpeed(MOVE_FLIGHT, true);
12967  }
12968 
12969  if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_ALLOW_MOUNTED_COMBAT))
12970  Dismount();
12971  if (!IsStandState()) // pussywizard: already done in CombatStart(target, initialAggro) for the target, but when aggro'ing from MoveInLOS CombatStart is not called!
12973  }
12974 
12975  for (Unit::ControlSet::iterator itr = m_Controlled.begin(); itr != m_Controlled.end();)
12976  {
12977  Unit* controlled = *itr;
12978  ++itr;
12979 
12980  // Xinef: Dont set combat for passive units, they will evade in next update...
12981  if (controlled->GetTypeId() == TYPEID_UNIT && controlled->ToCreature()->HasReactState(REACT_PASSIVE))
12982  continue;
12983 
12984  controlled->SetInCombatState(PvP, enemy);
12985  }
12986 #ifdef ELUNA
12987  if (Player* player = this->ToPlayer())
12988  sEluna->OnPlayerEnterCombat(player, enemy);
12989 #endif
12990 }
12991 
12993 {
12994  m_CombatTimer = 0;
12996 
12997  // Player's state will be cleared in Player::UpdateContestedPvP
12998  if (Creature* creature = ToCreature())
12999  {
13000  if (creature->GetCreatureTemplate() && creature->GetCreatureTemplate()->unit_flags & UNIT_FLAG_IMMUNE_TO_PC)
13001  SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); // set immunity state to the one from db on evade
13002 
13005  SetUInt32Value(UNIT_DYNAMIC_FLAGS, creature->GetCreatureTemplate()->dynamicflags);
13006 
13007  creature->SetAssistanceTimer(0);
13008 
13009  // Xinef: will be recalculated at follow movement generator initialization
13010  if (!IsPet() && !IsCharmed())
13011  return;
13012  }
13013  else if (Player* player = ToPlayer())
13014  {
13015  player->UpdatePotionCooldown();
13016  if (player->getClass() == CLASS_DEATH_KNIGHT)
13017  for (uint8 i = 0; i < MAX_RUNES; ++i)
13018  player->SetGracePeriod(i, 0);
13019  }
13020 #ifdef ELUNA
13021  if (Player* player = this->ToPlayer())
13022  sEluna->OnPlayerLeaveCombat(player);
13023 #endif
13024 }
13025 
13027 {
13030  if (Unit* owner = GetOwner())
13031  {
13032  owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
13033  }
13034 }
13035 
13036 bool Unit::isTargetableForAttack(bool checkFakeDeath, Unit const* byWho) const
13037 {
13038  if (!IsAlive())
13039  return false;
13040 
13042  return false;
13043 
13045  return false;
13046 
13047  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster())
13048  return false;
13049 
13050  return !HasUnitState(UNIT_STATE_UNATTACKABLE) && (!checkFakeDeath || !HasUnitState(UNIT_STATE_DIED));
13051 }
13052 
13053 bool Unit::IsValidAttackTarget(Unit const* target) const
13054 {
13055  return _IsValidAttackTarget(target, nullptr);
13056 }
13057 
13058 // function based on function Unit::CanAttack from 13850 client
13059 bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, WorldObject const* obj) const
13060 {
13061  ASSERT(target);
13062 
13063  // can't attack self
13064  if (this == target)
13065  return false;
13066 
13067  // can't attack unattackable units or GMs
13069  || (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster()))
13070  return false;
13071 
13072  // can't attack own vehicle or passenger
13073  if (m_vehicle)
13074  if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))
13075  if (!IsHostileTo(target)) // pussywizard: actually can attack own vehicle or passenger if it's hostile to us - needed for snobold in Gormok encounter
13076  return false;
13077 
13078  // can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit.
13079  //Ignore stealth if target is player and unit in combat with same player
13080  if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, (bySpell && bySpell->IsAffectingArea()) || (target->GetTypeId() == TYPEID_PLAYER && target->HasStealthAura() && target->IsInCombat() && IsInCombatWith(target)))))
13081  return false;
13082 
13083  // can't attack dead
13084  if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->IsAlive())
13085  return false;
13086 
13087  // can't attack untargetable
13088  if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
13090  return false;
13091 
13092  if (Player const* playerAttacker = ToPlayer())
13093  {
13094  if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UBER) || playerAttacker->IsSpectator())
13095  return false;
13096  }
13097  // check flags
13102  // check if this is a world trigger cast - GOs are using world triggers to cast their spells, so we need to ignore their immunity flag here, this is a temp workaround, needs removal when go cast is implemented properly
13104  return false;
13105 
13106  // CvC case - can attack each other only when one of them is hostile
13108  return GetReactionTo(target) <= REP_HOSTILE || target->GetReactionTo(this) <= REP_HOSTILE;
13109 
13110  // PvP, PvC, CvP case
13111  // can't attack friendly targets
13112  ReputationRank repThisToTarget = GetReactionTo(target);
13113  ReputationRank repTargetToThis;
13114 
13115  if (repThisToTarget > REP_NEUTRAL
13116  || (repTargetToThis = target->GetReactionTo(this)) > REP_NEUTRAL)
13117  return false;
13118 
13119  // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
13120  if (repThisToTarget == REP_NEUTRAL &&
13121  repTargetToThis <= REP_NEUTRAL)
13122  {
13123  Player* owner = GetAffectingPlayer();
13124  const Unit* const thisUnit = owner ? owner : this;
13125  if (!(target->GetTypeId() == TYPEID_PLAYER && thisUnit->GetTypeId() == TYPEID_PLAYER) &&
13126  !(target->GetTypeId() == TYPEID_UNIT && thisUnit->GetTypeId() == TYPEID_UNIT))
13127  {
13128  Player const* player = target->GetTypeId() == TYPEID_PLAYER ? target->ToPlayer() : thisUnit->ToPlayer();
13129  Unit const* creature = target->GetTypeId() == TYPEID_UNIT ? target : thisUnit;
13130 
13131  if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry())
13132  {
13133  if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate)))
13134  if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction))
13135  if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
13136  if (!(repState->Flags & FACTION_FLAG_AT_WAR))
13137  return false;
13138  }
13139  }
13140  }
13141 
13142  Creature const* creatureAttacker = ToCreature();
13143  if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)
13144  return false;
13145 
13146  Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : nullptr;
13147  Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) ? target->GetAffectingPlayer() : nullptr;
13148 
13149  // check duel - before sanctuary checks
13150  if (playerAffectingAttacker && playerAffectingTarget)
13151  if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0)
13152  return true;
13153 
13154  // PvP case - can't attack when attacker or target are in sanctuary
13155  // however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp
13157  return false;
13158 
13159  // additional checks - only PvP case
13160  if (playerAffectingAttacker && playerAffectingTarget)
13161  {
13162  if (target->IsPvP())
13163  return true;
13164 
13165  if (IsFFAPvP() && target->IsFFAPvP())
13166  return true;
13167 
13169  }
13170  return true;
13171 }
13172 
13173 bool Unit::IsValidAssistTarget(Unit const* target) const
13174 {
13175  return _IsValidAssistTarget(target, nullptr);
13176 }
13177 
13178 // function based on function Unit::CanAssist from 13850 client
13179 bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const
13180 {
13181  ASSERT(target);
13182 
13183  // can assist to self
13184  if (this == target)
13185  return true;
13186 
13187  // can't assist unattackable units or GMs
13189  || (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster()))
13190  return false;
13191 
13192  // can't assist own vehicle or passenger
13193  if (m_vehicle)
13194  if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))
13195  return false;
13196 
13197  // can't assist invisible
13198  if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
13199  return false;
13200 
13201  // can't assist dead
13202  if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && !target->IsAlive())
13203  return false;
13204 
13205  // can't assist untargetable
13206  if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
13208  return false;
13209 
13210  if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC))
13211  {
13212  // xinef: do not allow to assist non attackable units
13214  return false;
13215 
13217  {
13219  return false;
13220  }
13221  else
13222  {
13224  return false;
13225  }
13226  }
13227 
13228  // can't assist non-friendly targets
13229  if (GetReactionTo(target) < REP_NEUTRAL
13230  && target->GetReactionTo(this) < REP_NEUTRAL
13231  && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)))
13232  return false;
13233 
13234  // PvP case
13236  {
13237  Player const* targetPlayerOwner = target->GetAffectingPlayer();
13239  {
13240  Player const* selfPlayerOwner = GetAffectingPlayer();
13241  if (selfPlayerOwner && targetPlayerOwner)
13242  {
13243  // can't assist player which is dueling someone
13244  if (selfPlayerOwner != targetPlayerOwner
13245  && targetPlayerOwner->duel)
13246  return false;
13247  }
13248  // can't assist player in ffa_pvp zone from outside
13249  if (target->IsFFAPvP() && !IsFFAPvP())
13250  return false;
13251 
13252  // can't assist player out of sanctuary from sanctuary if has pvp enabled
13253  if (target->IsPvP())
13254  if (IsInSanctuary() && !target->IsInSanctuary())
13255  return false;
13256  }
13257  }
13258  // PvC case - player can assist creature only if has specific type flags
13259  // !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED) &&
13261  && (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC))
13262  && !target->IsPvP())
13263  {
13264  if (Creature const* creatureTarget = target->ToCreature())
13265  return creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT || creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST;
13266  }
13267  return true;
13268 }
13269 
13271 {
13272  int32 gain = 0;
13273 
13274  if (dVal == 0)
13275  return 0;
13276 
13277  int32 curHealth = (int32)GetHealth();
13278 
13279  int32 val = dVal + curHealth;
13280  if (val <= 0)
13281  {
13282  SetHealth(0);
13283  return -curHealth;
13284  }
13285 
13286  int32 maxHealth = (int32)GetMaxHealth();
13287 
13288  if (val < maxHealth)
13289  {
13290  SetHealth(val);
13291  gain = val - curHealth;
13292  }
13293  else if (curHealth != maxHealth)
13294  {
13295  SetHealth(maxHealth);
13296  gain = maxHealth - curHealth;
13297  }
13298 
13299  return gain;
13300 }
13301 
13303 {
13304  int32 gain = 0;
13305 
13306  if (dVal == 0)
13307  return 0;
13308 
13309  int32 curHealth = (int32)GetHealth();
13310 
13311  int32 val = dVal + curHealth;
13312  if (val <= 0)
13313  {
13314  return -curHealth;
13315  }
13316 
13317  int32 maxHealth = (int32)GetMaxHealth();
13318 
13319  if (val < maxHealth)
13320  gain = dVal;
13321  else if (curHealth != maxHealth)
13322  gain = maxHealth - curHealth;
13323 
13324  return gain;
13325 }
13326 
13327 // returns negative amount on power reduction
13329 {
13330  if (dVal == 0)
13331  return 0;
13332 
13333  int32 gain = 0;
13334 
13335  int32 curPower = (int32)GetPower(power);
13336 
13337  int32 val = dVal + curPower;
13338  if (val <= 0)
13339  {
13340  SetPower(power, 0);
13341  return -curPower;
13342  }
13343 
13344  int32 maxPower = (int32)GetMaxPower(power);
13345 
13346  if (val < maxPower)
13347  {
13348  SetPower(power, val);
13349  gain = val - curPower;
13350  }
13351  else if (curPower != maxPower)
13352  {
13353  SetPower(power, maxPower);
13354  gain = maxPower - curPower;
13355  }
13356 
13357  return gain;
13358 }
13359 
13360 // returns negative amount on power reduction
13361 int32 Unit::ModifyPowerPct(Powers power, float pct, bool apply)
13362 {
13363  float amount = (float)GetMaxPower(power);
13364  ApplyPercentModFloatVar(amount, pct, apply);
13365 
13366  return ModifyPower(power, (int32)amount - (int32)GetMaxPower(power));
13367 }
13368 
13369 bool Unit::IsAlwaysVisibleFor(WorldObject const* seer) const
13370 {
13372  return true;
13373 
13374  // Always seen by owner
13375  if (ObjectGuid guid = GetCharmerOrOwnerGUID())
13376  if (seer->GetGUID() == guid)
13377  return true;
13378 
13379  if (Player const* seerPlayer = seer->ToPlayer())
13380  if (Unit* owner = GetOwner())
13381  if (Player* ownerPlayer = owner->ToPlayer())
13382  if (ownerPlayer->IsGroupVisibleFor(seerPlayer))
13383  return true;
13384 
13385  return false;
13386 }
13387 
13389 {
13391  return true;
13392 
13394  return true;
13395 
13396  if (Player* ownerPlayer = GetSpellModOwner())
13397  if (const Player* seerPlayer = seer->ToPlayer())
13398  {
13399  if (ownerPlayer->IsGroupVisibleFor(seerPlayer))
13400  return true;
13401  }
13402 
13403  return false;
13404 }
13405 
13407 {
13408  if (!x)
13410  else
13412 
13414 }
13415 
13417 {
13418  if (on)
13419  RemoveAurasDueToSpell(24401);
13420  else
13421  CastSpell(this, 24401, true);
13422 }
13423 
13424 void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
13425 {
13426  int32 main_speed_mod = 0;
13427  float stack_bonus = 1.0f;
13428  float non_stack_bonus = 1.0f;
13429 
13430  switch (mtype)
13431  {
13432  // Only apply debuffs
13433  case MOVE_FLIGHT_BACK:
13434  case MOVE_RUN_BACK:
13435  case MOVE_SWIM_BACK:
13436  case MOVE_WALK:
13437  break;
13438  case MOVE_RUN:
13439  {
13440  if (IsMounted()) // Use on mount auras
13441  {
13445  }
13446  else
13447  {
13450  non_stack_bonus += GetMaxPositiveAuraModifier(SPELL_AURA_MOD_SPEED_NOT_STACK) / 100.0f;
13451  }
13452  break;
13453  }
13454  case MOVE_SWIM:
13455  {
13456  // xinef: check for forced_speed_mod of sea turtle
13458  for (Unit::AuraEffectList::const_iterator itr = swimAuras.begin(); itr != swimAuras.end(); ++itr)
13459  {
13460  // xinef: sea turtle only, it is not affected by any increasing / decreasing effects
13461  if ((*itr)->GetId() == 64731 /*SPELL_SEA_TURTLE*/)
13462  {
13463  SetSpeed(mtype, AddPct(non_stack_bonus, (*itr)->GetAmount()), forced);
13464  return;
13465  }
13466  else if (
13467  // case: increase speed
13468  ((*itr)->GetAmount() > 0 && (*itr)->GetAmount() > main_speed_mod) ||
13469  // case: decrease speed
13470  ((*itr)->GetAmount() < 0 && (*itr)->GetAmount() < main_speed_mod)
13471  )
13472  {
13473  main_speed_mod = (*itr)->GetAmount();
13474  }
13475  }
13476  break;
13477  }
13478  case MOVE_FLIGHT:
13479  {
13480  if (GetTypeId() == TYPEID_UNIT && IsControlledByPlayer()) // not sure if good for pet
13481  {
13484 
13485  // for some spells this mod is applied on vehicle owner
13486  int32 owner_speed_mod = 0;
13487 
13488  if (Unit* owner = GetCharmer())
13489  owner_speed_mod = owner->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED);
13490 
13491  main_speed_mod = std::max(main_speed_mod, owner_speed_mod);
13492  }
13493  else if (IsMounted())
13494  {
13497  }
13498  else // Use not mount (shapeshift for example) auras (should stack)
13500 
13502 
13503  // Update speed for vehicle if available
13504  if (GetTypeId() == TYPEID_PLAYER && GetVehicle())
13506  break;
13507  }
13508  default:
13509  LOG_ERROR("entities.unit", "Unit::UpdateSpeed: Unsupported move type (%d)", mtype);
13510  return;
13511  }
13512 
13513  // now we ready for speed calculation
13514  float speed = std::max(non_stack_bonus, stack_bonus);
13515  if (main_speed_mod)
13516  AddPct(speed, main_speed_mod);
13517 
13518  switch (mtype)
13519  {
13520  case MOVE_RUN:
13521  case MOVE_SWIM:
13522  case MOVE_FLIGHT:
13523  {
13524  if (GetTypeId() == TYPEID_UNIT)
13525  {
13526  speed *= ToCreature()->GetCreatureTemplate()->speed_run; // at this point, MOVE_WALK is never reached
13527  }
13528 
13529  // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need
13530  // TODO: possible affect only on MOVE_RUN
13532  {
13533  // Use speed from aura
13534  float max_speed = normalization / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]);
13535 
13536  // Xinef: normal movement speed - multiply by creature db modifer
13537  if (GetTypeId() == TYPEID_UNIT)
13538  max_speed *= ToCreature()->GetCreatureTemplate()->speed_run;
13539 
13540  if (speed > max_speed)
13541  speed = max_speed;
13542  }
13543  break;
13544  }
13545  default:
13546  break;
13547  }
13548 
13549  int32 slowFromHealth = 0;
13550  Creature* creature = ToCreature();
13551  // ignore pets, player owned vehicles, and mobs immune to snare
13552  if (creature
13553  && !IsPet()
13554  && !(IsControlledByPlayer() && IsVehicle())
13556  && !(creature->IsDungeonBoss()))
13557  {
13558  // 1.6% for each % under 30.
13559  // use min(0, health-30) so that we don't boost mobs above 30.
13560  slowFromHealth = (int32) std::min(0.0f, (1.66f * (GetHealthPct() - 30.0f)));
13561  }
13562 
13563  if (slowFromHealth)
13564  {
13565  AddPct(speed, slowFromHealth);
13566  }
13567 
13568  // Apply strongest slow aura mod to speed
13570  if (slow)
13571  AddPct(speed, slow);
13572 
13573  if (float minSpeedMod = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MINIMUM_SPEED))
13574  {
13575  float base_speed = (GetTypeId() == TYPEID_UNIT ? ToCreature()->GetCreatureTemplate()->speed_run : 1.0f);
13576  float min_speed = base_speed * (minSpeedMod / 100.0f);
13577  if (speed < min_speed)
13578  speed = min_speed;
13579  }
13580 
13581  SetSpeed(mtype, speed, forced);
13582 }
13583 
13584 float Unit::GetSpeed(UnitMoveType mtype) const
13585 {
13586  return m_speed_rate[mtype] * (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]);
13587 }
13588 
13589 void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
13590 {
13591  if (rate < 0)
13592  rate = 0.0f;
13593 
13594  // Update speed only on change
13595  if (m_speed_rate[mtype] == rate)
13596  return;
13597 
13598  m_speed_rate[mtype] = rate;
13599 
13601 
13602  WorldPacket data;
13603  if (!forced)
13604  {
13605  switch (mtype)
13606  {
13607  case MOVE_WALK:
13608  data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13609  break;
13610  case MOVE_RUN:
13611  data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13612  break;
13613  case MOVE_RUN_BACK:
13614  data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13615  break;
13616  case MOVE_SWIM:
13617  data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13618  break;
13619  case MOVE_SWIM_BACK:
13620  data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13621  break;
13622  case MOVE_TURN_RATE:
13623  data.Initialize(MSG_MOVE_SET_TURN_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13624  break;
13625  case MOVE_FLIGHT:
13626  data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13627  break;
13628  case MOVE_FLIGHT_BACK:
13629  data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13630  break;
13631  case MOVE_PITCH_RATE:
13632  data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
13633  break;
13634  default:
13635  LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
13636  return;
13637  }
13638 
13639  data << GetPackGUID();
13641  data << float(GetSpeed(mtype));
13642  SendMessageToSet(&data, true);
13643  }
13644  else
13645  {
13646  if (GetTypeId() == TYPEID_PLAYER)
13647  {
13648  // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
13649  // and do it only for real sent packets and use run for run/mounted as client expected
13650  ++ToPlayer()->m_forced_speed_changes[mtype];
13651 
13652  // Xinef: update speed of pet also
13653  if (!IsInCombat())
13654  {
13655  Unit* pet = ToPlayer()->GetPet();
13656  if (!pet)
13657  pet = GetCharm();
13658 
13659  // xinef: do not affect vehicles and possesed pets
13660  if (pet && (pet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED) || pet->IsVehicle()))
13661  pet = nullptr;
13662 
13664  pet->UpdateSpeed(mtype, forced);
13665  if (Unit* critter = ObjectAccessor::GetUnit(*this, GetCritterGUID()))
13666  critter->UpdateSpeed(mtype, forced);
13667  }
13668  }
13669 
13670  switch (mtype)
13671  {
13672  case MOVE_WALK:
13673  data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
13674  break;
13675  case MOVE_RUN:
13676  data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
13677  break;
13678  case MOVE_RUN_BACK:
13679  data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
13680  break;
13681  case MOVE_SWIM:
13682  data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
13683  break;
13684  case MOVE_SWIM_BACK:
13685  data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
13686  break;
13687  case MOVE_TURN_RATE:
13688  data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
13689  break;
13690  case MOVE_FLIGHT:
13691  data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
13692  break;
13693  case MOVE_FLIGHT_BACK:
13694  data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
13695  break;
13696  case MOVE_PITCH_RATE:
13697  data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
13698  break;
13699  default:
13700  LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
13701  return;
13702  }
13703  data << GetPackGUID();
13704  data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
13705  if (mtype == MOVE_RUN)
13706  data << uint8(0); // new 2.1.0
13707  data << float(GetSpeed(mtype));
13708  SendMessageToSet(&data, true);
13709  }
13710 }
13711 
13712 void Unit::setDeathState(DeathState s, bool despawn)
13713 {
13714  // death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that
13715  // it can be used to check creation of death items (such as soul shards).
13716 
13717  if (s != ALIVE && s != JUST_RESPAWNED)
13718  {
13719  CombatStop();
13720  DeleteThreatList();
13722  ClearComboPointHolders(); // any combo points pointed to unit lost at it death
13723 
13724  if (IsNonMeleeSpellCast(false))
13725  InterruptNonMeleeSpells(false);
13726 
13727  UnsummonAllTotems(true);
13728  RemoveAllControlled(true);
13730  }
13731 
13732  if (s == JUST_DIED)
13733  {
13737 
13738  // remove aurastates allowing special moves
13741 
13742  GetMotionMaster()->Clear(false);
13744 
13745  // Xinef: Remove Hover so the corpse can fall to the ground
13746  SetHover(false);
13747 
13748  if (despawn)
13749  DisableSpline();
13750  else
13751  StopMoving();
13752 
13753  // without this when removing IncreaseMaxHealth aura player may stuck with 1 hp
13754  // do not why since in IncreaseMaxHealth currenthealth is checked
13755  SetHealth(0);
13756  SetPower(getPowerType(), 0);
13757 
13758  // players in instance don't have ZoneScript, but they have InstanceScript
13759  if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : (ZoneScript*)GetInstanceScript())
13760  zoneScript->OnUnitDeath(this);
13761  }
13762  else if (s == JUST_RESPAWNED)
13763  {
13764  RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)
13765  }
13766 
13767  m_deathState = s;
13768 }
13769 
13770 /*########################################
13771 ######## ########
13772 ######## AGGRO SYSTEM ########
13773 ######## ########
13774 ########################################*/
13776 {
13777  // only creatures can have threat list
13778  if (GetTypeId() != TYPEID_UNIT)
13779  return false;
13780 
13781  // only alive units can have threat list
13782  if (!IsAlive() || isDying())
13783  return false;
13784 
13785  // totems can not have threat list
13786  if (ToCreature()->IsTotem())
13787  return false;
13788 
13789  // vehicles can not have threat list
13790  if (ToCreature()->IsVehicle() && GetMap()->IsBattlegroundOrArena())
13791  return false;
13792 
13793  // summons can not have a threat list, unless they are controlled by a creature
13795  return false;
13796 
13797  return true;
13798 }
13799 
13800 //======================================================================
13801 
13802 float Unit::ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask)
13803 {
13804  if (!HasAuraType(SPELL_AURA_MOD_THREAT) || fThreat < 0)
13805  return fThreat;
13806 
13807  SpellSchools school = GetFirstSchoolInMask(schoolMask);
13808 
13809  return fThreat * m_threatModifier[school];
13810 }
13811 
13812 //======================================================================
13813 
13814 void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, SpellInfo const* threatSpell)
13815 {
13816  // Only mobs can manage threat lists
13818  {
13819  m_ThreatMgr.addThreat(victim, fThreat, schoolMask, threatSpell);
13820  }
13821 }
13822 
13823 //======================================================================
13824 
13826 {
13830 }
13831 
13832 //======================================================================
13833 
13834 void Unit::TauntApply(Unit* taunter)
13835 {
13837 
13838  if (!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && taunter->ToPlayer()->IsGameMaster()))
13839  return;
13840 
13841  if (!CanHaveThreatList())
13842  return;
13843 
13844  Creature* creature = ToCreature();
13845 
13846  if (creature->HasReactState(REACT_PASSIVE))
13847  return;
13848 
13849  Unit* target = GetVictim();
13850  if (target && target == taunter)
13851  return;
13852 
13853  SetInFront(taunter);
13854  if (creature->IsAIEnabled)
13855  creature->AI()->AttackStart(taunter);
13856 
13857  //m_ThreatMgr.tauntApply(taunter);
13858 }
13859 
13860 //======================================================================
13861 
13862 void Unit::TauntFadeOut(Unit* taunter)
13863 {
13865 
13866  if (!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && taunter->ToPlayer()->IsGameMaster()))
13867  return;
13868 
13869  if (!CanHaveThreatList())
13870  return;
13871 
13872  Creature* creature = ToCreature();
13873 
13874  if (creature->HasReactState(REACT_PASSIVE))
13875  return;
13876 
13877  Unit* target = GetVictim();
13878  if (!target || target != taunter)
13879  return;
13880 
13882  {
13883  if (creature->IsAIEnabled)
13884  creature->AI()->EnterEvadeMode();
13885  return;
13886  }
13887 
13888  target = creature->SelectVictim(); // might have more taunt auras remaining
13889 
13890  if (target && target != taunter)
13891  {
13892  SetInFront(target);
13893  if (creature->IsAIEnabled)
13894  creature->AI()->AttackStart(target);
13895  }
13896 }
13897 
13898 //======================================================================
13899 
13901 {
13902  // function provides main threat functionality
13903  // next-victim-selection algorithm and evade mode are called
13904  // threat list sorting etc.
13905 
13906  Unit* target = nullptr;
13907 
13908  // First checking if we have some taunt on us
13910  if (!tauntAuras.empty())
13911  for (Unit::AuraEffectList::const_reverse_iterator itr = tauntAuras.rbegin(); itr != tauntAuras.rend(); ++itr)
13912  if (Unit* caster = (*itr)->GetCaster())
13913  if (_CanDetectFeignDeathOf(caster) && CanCreatureAttack(caster) && !caster->HasAuraTypeWithCaster(SPELL_AURA_IGNORED, GetGUID()))
13914  {
13915  target = caster;
13916  break;
13917  }
13918 
13919  if (CanHaveThreatList())
13920  {
13921  if (!target && !m_ThreatMgr.isThreatListEmpty())
13922  target = m_ThreatMgr.getHostilTarget();
13923  }
13924  else if (!HasReactState(REACT_PASSIVE))
13925  {
13926  // we have player pet probably
13927  target = getAttackerForHelper();
13928  if (!target && IsSummon())
13929  if (Unit* owner = ToTempSummon()->GetOwner())
13930  {
13931  if (owner->IsInCombat())
13932  target = owner->getAttackerForHelper();
13933  if (!target)
13934  for (ControlSet::const_iterator itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end(); ++itr)
13935  if ((*itr)->IsInCombat())
13936  {
13937  target = (*itr)->getAttackerForHelper();
13938  if (target)
13939  break;
13940  }
13941  }
13942  }
13943  else
13944  return nullptr;
13945 
13946  if (target && _CanDetectFeignDeathOf(target) && CanCreatureAttack(target))
13947  {
13948  SetInFront(target);
13949  return target;
13950  }
13951 
13952  // last case when creature must not go to evade mode:
13953  // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
13954  // Note: creature does not have targeted movement generator but has attacker in this case
13955  for (AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
13956  if ((*itr) && CanCreatureAttack(*itr) && (*itr)->GetTypeId() != TYPEID_PLAYER && !(*itr)->ToCreature()->HasUnitTypeMask(UNIT_MASK_CONTROLABLE_GUARDIAN))
13957  return nullptr;
13958 
13959  if (GetVehicle())
13960  return nullptr;
13961 
13962  // pussywizard: not sure why it's here
13963  // pussywizard: can't evade when having invisibility aura with duration? o_O
13965  if (!iAuras.empty())
13966  {
13967  for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr)
13968  if ((*itr)->GetBase()->IsPermanent())
13969  {
13970  AI()->EnterEvadeMode();
13971  break;
13972  }
13973  return nullptr;
13974  }
13975 
13976  // enter in evade mode in other case
13977  AI()->EnterEvadeMode();
13978 
13979  return nullptr;
13980 }
13981 
13982 //======================================================================
13983 //======================================================================
13984 //======================================================================
13985 
13986 float Unit::ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index, float value) const
13987 {
13988  if (Player* modOwner = GetSpellModOwner())
13989  {
13990  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_ALL_EFFECTS, value);
13991  switch (effect_index)
13992  {
13993  case 0:
13994  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT1, value);
13995  break;
13996  case 1:
13997  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT2, value);
13998  break;
13999  case 2:
14000  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_EFFECT3, value);
14001  break;
14002  }
14003  }
14004  return value;
14005 }
14006 
14007 // function uses real base points (typically value - 1)
14008 int32 Unit::CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints) const
14009 {
14010  return spellProto->Effects[effect_index].CalcValue(this, basePoints, target);
14011 }
14012 
14014 {
14015  uint8 comboPoints = m_movedByPlayer ? m_movedByPlayer->ToPlayer()->GetComboPoints() : 0;
14016 
14017  int32 minduration = spellProto->GetDuration();
14018  int32 maxduration = spellProto->GetMaxDuration();
14019 
14020  int32 duration;
14021 
14022  if (comboPoints && minduration != -1 && minduration != maxduration)
14023  duration = minduration + int32((maxduration - minduration) * comboPoints / 5);
14024  else
14025  duration = minduration;
14026 
14027  return duration;
14028 }
14029 
14030 int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, int32 duration, bool positive, uint32 effectMask)
14031 {
14032  // don't mod permanent auras duration
14033  if (duration < 0)
14034  return duration;
14035 
14036  // some auras are not affected by duration modifiers
14038  return duration;
14039 
14040  // cut duration only of negative effects
14041  // xinef: also calculate self casts, spell can be reflected for example
14042  if (!positive)
14043  {
14044  int32 mechanic = spellProto->GetSpellMechanicMaskByEffectMask(effectMask);
14045 
14046  int32 durationMod;
14047  int32 durationMod_always = 0;
14048  int32 durationMod_not_stack = 0;
14049 
14050  for (uint8 i = 1; i <= MECHANIC_ENRAGED; ++i)
14051  {
14052  if (!(mechanic & 1 << i))
14053  continue;
14054 
14055  // Xinef: spells affecting movement imparing effects should not reduce duration if disoriented mechanic is present
14056  if (i == MECHANIC_SNARE && (mechanic & (1 << MECHANIC_DISORIENTED)))
14057  continue;
14058 
14059  // Find total mod value (negative bonus)
14060  int32 new_durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, i);
14061  // Find max mod (negative bonus)
14063  // Check if mods applied before were weaker
14064  if (new_durationMod_always < durationMod_always)
14065  durationMod_always = new_durationMod_always;
14066  if (new_durationMod_not_stack < durationMod_not_stack)
14067  durationMod_not_stack = new_durationMod_not_stack;
14068  }
14069 
14070  // Select strongest negative mod
14071  if (durationMod_always > durationMod_not_stack)
14072  durationMod = durationMod_not_stack;
14073  else
14074  durationMod = durationMod_always;
14075 
14076  if (durationMod != 0)
14077  AddPct(duration, durationMod);
14078 
14079  // there are only negative mods currently
14080  durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL, spellProto->Dispel);
14082 
14083  durationMod = 0;
14084  if (durationMod_always > durationMod_not_stack)
14085  durationMod += durationMod_not_stack;
14086  else
14087  durationMod += durationMod_always;
14088 
14089  if (durationMod != 0)
14090  AddPct(duration, durationMod);
14091  }
14092  else
14093  {
14094  // else positive mods here, there are no currently
14095  // when there will be, change GetTotalAuraModifierByMiscValue to GetTotalPositiveAuraModifierByMiscValue
14096  }
14097 
14098  // Glyphs which increase duration of selfcasted buffs
14099  if (target == this)
14100  {
14101  switch (spellProto->SpellFamilyName)
14102  {
14103  case SPELLFAMILY_DRUID:
14104  if (spellProto->SpellFamilyFlags[0] & 0x100)
14105  {
14106  // Glyph of Thorns
14107  if (AuraEffect* aurEff = GetAuraEffect(57862, 0))
14108  duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
14109  }
14110  break;
14111  case SPELLFAMILY_PALADIN:
14112  if ((spellProto->SpellFamilyFlags[0] & 0x00000002) && spellProto->SpellIconID == 298)
14113  {
14114  // Glyph of Blessing of Might
14115  if (AuraEffect* aurEff = GetAuraEffect(57958, 0))
14116  duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
14117  }
14118  else if ((spellProto->SpellFamilyFlags[0] & 0x00010000) && spellProto->SpellIconID == 306)
14119  {
14120  // Glyph of Blessing of Wisdom
14121  if (AuraEffect* aurEff = GetAuraEffect(57979, 0))
14122  duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
14123  }
14124  break;
14125  }
14126  }
14127  return std::max(duration, 0);
14128 }
14129 
14130 void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32& castTime, Spell* spell)
14131 {
14132  if (!spellInfo || castTime < 0)
14133  return;
14134 
14135  if (spellInfo->IsChanneled() && spellInfo->HasAura(SPELL_AURA_MOUNTED))
14136  return;
14137 
14138  // called from caster
14139  if (Player* modOwner = GetSpellModOwner())
14140  // TODO:(MadAgos) Eventually check and delete the bool argument
14141  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell, bool(modOwner != this && !IsPet()));
14142 
14143  switch (spellInfo->DmgClass)
14144  {
14146  if (spellInfo->AttributesEx5 & SPELL_ATTR5_SPELL_HASTE_AFFECTS_PERIODIC) // required double check
14147  castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED));
14148  else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat.
14149  castTime = 500;
14150  break;
14152  break; // no known cases
14154  castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED));
14155  break;
14157  castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]);
14158  break;
14159  default:
14160  break;
14161  }
14162 }
14163 
14165 {
14166  for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
14167  {
14168  if (i->DRGroup != group)
14169  continue;
14170 
14171  if (!i->hitCount)
14172  return DIMINISHING_LEVEL_1;
14173 
14174  if (!i->hitTime)
14175  return DIMINISHING_LEVEL_1;
14176 
14177  // If last spell was casted more than 15 seconds ago - reset the count.
14178  if (i->stack == 0 && getMSTimeDiff(i->hitTime, World::GetGameTimeMS()) > 15000)
14179  {
14180  i->hitCount = DIMINISHING_LEVEL_1;
14181  return DIMINISHING_LEVEL_1;
14182  }
14183  // or else increase the count.
14184  else
14185  return DiminishingLevels(i->hitCount);
14186  }
14187  return DIMINISHING_LEVEL_1;
14188 }
14189 
14191 {
14192  // Checking for existing in the table
14193  for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
14194  {
14195  if (i->DRGroup != group)
14196  continue;
14197  if (int32(i->hitCount) < GetDiminishingReturnsMaxLevel(group))
14198  i->hitCount += 1;
14199  return;
14200  }
14202 }
14203 
14204 float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32& duration, Unit* caster, DiminishingLevels Level, int32 limitduration)
14205 {
14206  // xinef: dont apply diminish to self casts
14207  if (duration == -1 || group == DIMINISHING_NONE)
14208  return 1.0f;
14209 
14210  // test pet/charm masters instead pets/charmeds
14211  Unit const* targetOwner = GetOwner();
14212  Unit const* casterOwner = caster->GetOwner();
14213 
14214  // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0)
14215  if (limitduration > 0 && duration > limitduration)
14216  {
14217  Unit const* target = targetOwner ? targetOwner : this;
14218  Unit const* source = casterOwner ? casterOwner : caster;
14219 
14220  if ((target->GetTypeId() == TYPEID_PLAYER
14222  && source->GetTypeId() == TYPEID_PLAYER)
14223  duration = limitduration;
14224  }
14225 
14226  float mod = 1.0f;
14227 
14228  if (group == DIMINISHING_TAUNT)
14229  {
14230  if (GetTypeId() == TYPEID_UNIT && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_OBEYS_TAUNT_DIMINISHING_RETURNS))
14231  {
14232  DiminishingLevels diminish = Level;
14233  switch (diminish)
14234  {
14235  case DIMINISHING_LEVEL_1:
14236  break;
14237  case DIMINISHING_LEVEL_2:
14238  mod = 0.65f;
14239  break;
14240  case DIMINISHING_LEVEL_3:
14241  mod = 0.4225f;
14242  break;
14243  case DIMINISHING_LEVEL_4:
14244  mod = 0.274625f;
14245  break;
14247  mod = 0.0f;
14248  break;
14249  default:
14250  break;
14251  }
14252  }
14253  }
14254  // Some diminishings applies to mobs too (for example, Stun)
14255  else if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER
14256  && ((targetOwner ? (targetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER))
14257  || (GetTypeId() == TYPEID_UNIT && ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH)))
14259  {
14260  DiminishingLevels diminish = Level;
14261  switch (diminish)
14262  {
14263  case DIMINISHING_LEVEL_1:
14264  break;
14265  case DIMINISHING_LEVEL_2:
14266  mod = 0.5f;
14267  break;
14268  case DIMINISHING_LEVEL_3:
14269  mod = 0.25f;
14270  break;
14272  mod = 0.0f;
14273  break;
14274  default:
14275  break;
14276  }
14277  }
14278 
14279  duration = int32(duration * mod);
14280  return mod;
14281 }
14282 
14284 {
14285  // Checking for existing in the table
14286  for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
14287  {
14288  if (i->DRGroup != group)
14289  continue;
14290 
14291  if (apply)
14292  i->stack += 1;
14293  else if (i->stack)
14294  {
14295  i->stack -= 1;
14296  // Remember time after last aura from group removed
14297  if (i->stack == 0)
14298  i->hitTime = World::GetGameTimeMS();
14299  }
14300  break;
14301  }
14302 }
14303 
14304 float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
14305 {
14306  if (!spellInfo->RangeEntry)
14307  return 0;
14308  if (spellInfo->RangeEntry->maxRangeFriend == spellInfo->RangeEntry->maxRangeHostile)
14309  return spellInfo->GetMaxRange();
14310  if (target == nullptr)
14311  return spellInfo->GetMaxRange(true);
14312  return spellInfo->GetMaxRange(!IsHostileTo(target));
14313 }
14314 
14315 float Unit::GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
14316 {
14317  if (!spellInfo->RangeEntry)
14318  return 0;
14319  if (spellInfo->RangeEntry->minRangeFriend == spellInfo->RangeEntry->minRangeHostile)
14320  return spellInfo->GetMinRange();
14321  return spellInfo->GetMinRange(!IsHostileTo(target));
14322 }
14323 
14325 {
14326  if (GetTypeId() == TYPEID_PLAYER)
14327  {
14329  SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(form);
14330  if (ssEntry && ssEntry->creatureType > 0)
14331  return ssEntry->creatureType;
14332  else
14333  return CREATURE_TYPE_HUMANOID;
14334  }
14335  else
14336  return ToCreature()->GetCreatureTemplate()->type;
14337 }
14338 
14339 /*#######################################
14340 ######## ########
14341 ######## STAT SYSTEM ########
14342 ######## ########
14343 #######################################*/
14344 
14345 bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
14346 {
14347  if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
14348  {
14349  LOG_ERROR("entities.unit", "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!");
14350  return false;
14351  }
14352 
14353  switch (modifierType)
14354  {
14355  case BASE_VALUE:
14356  case TOTAL_VALUE:
14357  m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
14358  break;
14359  case BASE_PCT:
14360  case TOTAL_PCT:
14361  ApplyPercentModFloatVar(m_auraModifiersGroup[unitMod][modifierType], amount, apply);
14362  break;
14363  default:
14364  break;
14365  }
14366 
14367  if (!CanModifyStats())
14368  return false;
14369 
14370  switch (unitMod)
14371  {
14373  case UNIT_MOD_STAT_AGILITY:
14374  case UNIT_MOD_STAT_STAMINA:
14376  case UNIT_MOD_STAT_SPIRIT:
14377  UpdateStats(GetStatByAuraGroup(unitMod));
14378  break;
14379 
14380  case UNIT_MOD_ARMOR:
14381  UpdateArmor();
14382  break;
14383  case UNIT_MOD_HEALTH:
14384  UpdateMaxHealth();
14385  break;
14386 
14387  case UNIT_MOD_MANA:
14388  case UNIT_MOD_RAGE:
14389  case UNIT_MOD_FOCUS:
14390  case UNIT_MOD_ENERGY:
14391  case UNIT_MOD_HAPPINESS:
14392  case UNIT_MOD_RUNE:
14393  case UNIT_MOD_RUNIC_POWER:
14395  break;
14396 
14404  break;
14405 
14406  case UNIT_MOD_ATTACK_POWER:
14408  break;
14411  break;
14412 
14415  break;
14418  break;
14421  break;
14422 
14423  default:
14424  break;
14425  }
14426 
14427  return true;
14428 }
14429 
14430 float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const
14431 {
14432  if (unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
14433  {
14434  LOG_ERROR("entities.unit", "attempt to access non-existing modifier value from UnitMods!");
14435  return 0.0f;
14436  }
14437 
14438  if (modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
14439  return 0.0f;
14440 
14441  return m_auraModifiersGroup[unitMod][modifierType];
14442 }
14443 
14444 float Unit::GetTotalStatValue(Stats stat, float additionalValue) const
14445 {
14446  UnitMods unitMod = UnitMods(static_cast<uint16>(UNIT_MOD_STAT_START) + stat);
14447 
14448  if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
14449  return 0.0f;
14450 
14451  // value = ((base_value * base_pct) + total_value) * total_pct
14452  float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
14453  value *= m_auraModifiersGroup[unitMod][BASE_PCT];
14454  value += m_auraModifiersGroup[unitMod][TOTAL_VALUE] + additionalValue;
14455  value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
14456 
14457  return value;
14458 }
14459 
14461 {
14462  if (unitMod >= UNIT_MOD_END)
14463  {
14464  LOG_ERROR("entities.unit", "attempt to access non-existing UnitMods in GetTotalAuraModValue()!");
14465  return 0.0f;
14466  }
14467 
14468  if (m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
14469  return 0.0f;
14470 
14471  float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
14472  value *= m_auraModifiersGroup[unitMod][BASE_PCT];
14473  value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
14474  value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
14475 
14476  return value;
14477 }
14478 
14479 void Unit::ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
14480 {
14481  if (val == -100.0f) // prevent set var to zero
14482  val = -99.99f;
14483  float var = GetStat(stat) * val / 100.0f;
14484  ApplyModSignedFloatValue((var > 0 ? static_cast<uint16>(UNIT_FIELD_POSSTAT0) + stat : static_cast<uint16>(UNIT_FIELD_NEGSTAT0) + stat), var, apply);
14485 }
14486 
14488 {
14490 
14491  switch (unitMod)
14492  {
14494  school = SPELL_SCHOOL_HOLY;
14495  break;
14497  school = SPELL_SCHOOL_FIRE;
14498  break;
14500  school = SPELL_SCHOOL_NATURE;
14501  break;
14503  school = SPELL_SCHOOL_FROST;
14504  break;
14506  school = SPELL_SCHOOL_SHADOW;
14507  break;
14509  school = SPELL_SCHOOL_ARCANE;
14510  break;
14511 
14512  default:
14513  break;
14514  }
14515 
14516  return school;
14517 }
14518 
14520 {
14521  Stats stat = STAT_STRENGTH;
14522 
14523  switch (unitMod)
14524  {
14526  stat = STAT_STRENGTH;
14527  break;
14528  case UNIT_MOD_STAT_AGILITY:
14529  stat = STAT_AGILITY;
14530  break;
14531  case UNIT_MOD_STAT_STAMINA:
14532  stat = STAT_STAMINA;
14533  break;
14535  stat = STAT_INTELLECT;
14536  break;
14537  case UNIT_MOD_STAT_SPIRIT:
14538  stat = STAT_SPIRIT;
14539  break;
14540 
14541  default:
14542  break;
14543  }
14544 
14545  return stat;
14546 }
14547 
14549 {
14550  switch (unitMod)
14551  {
14552  case UNIT_MOD_RAGE:
14553  return POWER_RAGE;
14554  case UNIT_MOD_FOCUS:
14555  return POWER_FOCUS;
14556  case UNIT_MOD_ENERGY:
14557  return POWER_ENERGY;
14558  case UNIT_MOD_HAPPINESS:
14559  return POWER_HAPPINESS;
14560  case UNIT_MOD_RUNE:
14561  return POWER_RUNE;
14562  case UNIT_MOD_RUNIC_POWER:
14563  return POWER_RUNIC_POWER;
14564  default:
14565  case UNIT_MOD_MANA:
14566  return POWER_MANA;
14567  }
14568 }
14569 
14571 {
14572  if (attType == RANGED_ATTACK)
14573  {
14575  if( victim )
14577 
14578  if (ap < 0)
14579  return 0.0f;
14581  }
14582  else
14583  {
14585  if( victim )
14587 
14588  if (ap < 0)
14589  return 0.0f;
14590  return ap * (1.0f + GetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER));
14591  }
14592 }
14593 
14595 {
14596  if (attType == OFF_ATTACK && !haveOffhandWeapon())
14597  return 0.0f;
14598 
14599  return m_weaponDamage[attType][type];
14600 }
14601 
14602 void Unit::SetLevel(uint8 lvl, bool showLevelChange)
14603 {
14605 
14606  // Xinef: unmark field bit update
14607  if (!showLevelChange)
14609 
14610  // group update
14611  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup())
14613 
14614  // xinef: update global data
14615  if (GetTypeId() == TYPEID_PLAYER)
14616  sWorld->UpdateGlobalPlayerData(ToPlayer()->GetGUID().GetCounter(), PLAYER_UPDATE_DATA_LEVEL, "", lvl);
14617 }
14618 
14620 {
14621  if (getDeathState() == JUST_DIED)
14622  val = 0;
14623  else if (GetTypeId() == TYPEID_PLAYER && getDeathState() == DEAD)
14624  val = 1;
14625  else
14626  {
14627  uint32 maxHealth = GetMaxHealth();
14628  if (maxHealth < val)
14629  val = maxHealth;
14630  }
14631 
14632  float prevHealthPct = GetHealthPct();
14633 
14635 
14636  // mobs that are now or were below 30% need to update their speed
14637  if (GetTypeId() == TYPEID_UNIT && (prevHealthPct < 30.0 || HealthBelowPct(30)))
14638  {
14639  UpdateSpeed(MOVE_RUN, false);
14640  }
14641 
14642  // group update
14643  if (GetTypeId() == TYPEID_PLAYER)
14644  {
14645  Player* player = ToPlayer();
14646  if (player->NeedSendSpectatorData())
14648 
14649  if (player->GetGroup())
14651  }
14652  else if (Pet* pet = ToCreature()->ToPet())
14653  {
14654  if (pet->isControlled())
14655  {
14656  if (Unit* owner = GetOwner())
14657  if (Player* player = owner->ToPlayer())
14658  {
14659  if (player->NeedSendSpectatorData() && pet->GetCreatureTemplate()->family)
14660  ArenaSpectator::SendCommand_UInt32Value(player->FindMap(), player->GetGUID(), "PHP", (uint32)pet->GetHealthPct());
14661 
14662  if (player->GetGroup())
14663  player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
14664  }
14665  }
14666  }
14667 }
14668 
14670 {
14671  if (!val)
14672  val = 1;
14673 
14674  uint32 health = GetHealth();
14676 
14677  // group update
14678  if (GetTypeId() == TYPEID_PLAYER)
14679  {
14680  Player* player = ToPlayer();
14681  if (player->NeedSendSpectatorData())
14683 
14684  if (player->GetGroup())
14686  }
14687  else if (Pet* pet = ToCreature()->ToPet())
14688  {
14689  if (pet->isControlled())
14690  {
14691  if (Unit* owner = GetOwner())
14692  if (Player* player = owner->ToPlayer())
14693  {
14694  if (player->NeedSendSpectatorData() && pet->GetCreatureTemplate()->family)
14695  ArenaSpectator::SendCommand_UInt32Value(player->FindMap(), player->GetGUID(), "PHP", (uint32)pet->GetHealthPct());
14696 
14697  if (player->GetGroup())
14698  player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
14699  }
14700  }
14701  }
14702 
14703  if (val < health)
14704  SetHealth(val);
14705 }
14706 
14707 void Unit::SetPower(Powers power, uint32 val)
14708 {
14709  if (GetPower(power) == val)
14710  return;
14711 
14712  uint32 maxPower = GetMaxPower(power);
14713  if (maxPower < val)
14714  val = maxPower;
14715 
14716  SetStatInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power, val);
14717 
14719  data << GetPackGUID();
14720  data << uint8(power);
14721  data << uint32(val);
14723 
14724  // group update
14725  if (GetTypeId() == TYPEID_PLAYER)
14726  {
14727  Player* player = ToPlayer();
14728  if (getPowerType() == power && player->NeedSendSpectatorData())
14729  ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "CPW", power == POWER_RAGE || power == POWER_RUNIC_POWER ? val / 10 : val);
14730 
14731  if (player->GetGroup())
14733  }
14734  else if (Pet* pet = ToCreature()->ToPet())
14735  {
14736  if (pet->isControlled())
14737  {
14738  Unit* owner = GetOwner();
14739  if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
14741  }
14742 
14743  // Update the pet's character sheet with happiness damage bonus
14744  if (pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
14745  pet->UpdateDamagePhysical(BASE_ATTACK);
14746  }
14747 }
14748 
14750 {
14751  uint32 cur_power = GetPower(power);
14752  SetStatInt32Value(static_cast<uint16>(UNIT_FIELD_MAXPOWER1) + power, val);
14753 
14754  // group update
14755  if (GetTypeId() == TYPEID_PLAYER)
14756  {
14757  Player* player = ToPlayer();
14758  if (getPowerType() == power && player->NeedSendSpectatorData())
14759  ArenaSpectator::SendCommand_UInt32Value(FindMap(), GetGUID(), "MPW", power == POWER_RAGE || power == POWER_RUNIC_POWER ? val / 10 : val);
14760 
14761  if (player->GetGroup())
14763  }
14764  else if (Pet* pet = ToCreature()->ToPet())
14765  {
14766  if (pet->isControlled())
14767  {
14768  Unit* owner = GetOwner();
14769  if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
14771  }
14772  }
14773 
14774  if (val < cur_power)
14775  SetPower(power, val);
14776 }
14777 
14779 {
14780  // Only hunter pets have POWER_FOCUS and POWER_HAPPINESS
14781  switch (power)
14782  {
14783  case POWER_MANA:
14784  return GetCreateMana();
14785  case POWER_RAGE:
14786  return 1000;
14787  case POWER_FOCUS:
14788  return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100);
14789  case POWER_ENERGY:
14790  return 100;
14791  case POWER_HAPPINESS:
14792  return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 1050000);
14793  case POWER_RUNIC_POWER:
14794  return 1000;
14795  case POWER_RUNE:
14796  return 0;
14797  case POWER_HEALTH:
14798  return 0;
14799  default:
14800  break;
14801  }
14802 
14803  return 0;
14804 }
14805 
14807 {
14808  if (!IsInWorld())
14809  {
14811  }
14812 }
14813 
14815 {
14816  // cleanup
14817  ASSERT(GetGUID());
14818 
14819  if (IsInWorld())
14820  {
14821  m_duringRemoveFromWorld = true;
14822  if (IsVehicle())
14823  RemoveVehicleKit();
14824 
14825  RemoveCharmAuras();
14828 
14831 
14832  ExitVehicle(); // Remove applied auras with SPELL_AURA_CONTROL_VEHICLE
14835 
14837 
14838  if (GetCharmerGUID())
14839  {
14840  LOG_FATAL("entities.unit", "Unit %u has charmer guid when removed from world", GetEntry());
14841  ABORT();
14842  }
14843 
14844  if (Unit* owner = GetOwner())
14845  {
14846  if (owner->m_Controlled.find(this) != owner->m_Controlled.end())
14847  {
14849  owner->SetMinion((Minion*)this, false);
14850  LOG_INFO("entities.unit", "Unit %u is in controlled list of %u when removed from world", GetEntry(), owner->GetEntry());
14851  //ABORT();
14852  }
14853  }
14854 
14856  m_duringRemoveFromWorld = false;
14857  }
14858 }
14859 
14860 void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
14861 {
14863  return;
14864 
14865  // This needs to be before RemoveFromWorld to make GetCaster() return a valid pointer on aura removal
14867 
14868  if (IsInWorld()) // not in world and not being removed atm
14869  RemoveFromWorld();
14870 
14871  ASSERT(GetGUID());
14872 
14873  // A unit may be in removelist and not in world, but it is still in grid
14874  // and may have some references during delete
14875  RemoveAllAuras();
14877 
14878  if (finalCleanup)
14879  m_cleanupDone = true;
14880 
14881  m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
14882  CombatStop();
14884  DeleteThreatList();
14886  GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
14887 }
14888 
14889 void Unit::CleanupsBeforeDelete(bool finalCleanup)
14890 {
14891  if (GetTransport())
14892  {
14893  GetTransport()->RemovePassenger(this);
14894  SetTransport(nullptr);
14897  }
14898 
14899  CleanupBeforeRemoveFromMap(finalCleanup);
14900 }
14901 
14903 {
14904  if (GetTypeId() == TYPEID_PLAYER)
14905  return;
14906 
14907  if (i_disabledAI) // disabled AI must be primary AI
14908  {
14909  if (!IsCharmed())
14910  {
14911  delete i_AI;
14912  i_AI = i_disabledAI;
14913  i_disabledAI = nullptr;
14914  }
14915  }
14916  else
14917  {
14918  if (IsCharmed())
14919  {
14920  i_disabledAI = i_AI;
14921  if (isPossessed() || IsVehicle())
14922  i_AI = new PossessedAI(ToCreature());
14923  else
14924  i_AI = new PetAI(ToCreature());
14925  }
14926  }
14927 }
14928 
14930 {
14931  if (!m_charmInfo)
14932  m_charmInfo = new CharmInfo(this);
14933 
14934  return m_charmInfo;
14935 }
14936 
14938 {
14939  if (!m_charmInfo)
14940  return;
14941 
14943  delete m_charmInfo;
14944  m_charmInfo = nullptr;
14945 }
14946 
14948  : _unit(unit), _CommandState(COMMAND_FOLLOW), _petnumber(0), _oldReactState(REACT_PASSIVE),
14949  _isCommandAttack(false), _isCommandFollow(false), _isAtStay(false), _isFollowing(false), _isReturning(false),
14950  _forcedSpellId(0), _stayX(0.0f), _stayY(0.0f), _stayZ(0.0f)
14951 {
14952  for (uint8 i = 0; i < MAX_SPELL_CHARM; ++i)
14953  _charmspells[i].SetActionAndType(0, ACT_DISABLED);
14954 
14955  if (_unit->GetTypeId() == TYPEID_UNIT)
14956  {
14959  }
14960 }
14961 
14963 {
14964 }
14965 
14967 {
14968  if (Creature* creature = _unit->ToCreature())
14969  creature->SetReactState(_oldReactState);
14970 }
14971 
14973 {
14974  // the first 3 SpellOrActions are attack, follow and stay
14977 
14978  // middle 4 SpellOrActions are spells/special attacks/abilities
14981 
14982  // last 3 SpellOrActions are reactions
14985 }
14986 
14987 void CharmInfo::InitEmptyActionBar(bool withAttack)
14988 {
14989  if (withAttack)
14991  else
14994  SetActionBar(x, 0, ACT_PASSIVE);
14995 }
14996 
14998 {
14999  if (_unit->GetTypeId() == TYPEID_UNIT)
15000  {
15001  // Adding switch until better way is found. Malcrom
15002  // Adding entrys to this switch will prevent COMMAND_ATTACK being added to pet bar.
15003  switch (_unit->GetEntry())
15004  {
15005  case 23575: // Mindless Abomination
15006  case 24783: // Trained Rock Falcon
15007  case 27664: // Crashin' Thrashin' Racer
15008  case 40281: // Crashin' Thrashin' Racer
15009  case 23109: // Vengeful Spirit
15010  break;
15011  default:
15013  break;
15014  }
15015 
15016  for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i)
15017  {
15018  uint32 spellId = _unit->ToCreature()->m_spells[i];
15019  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
15020  if (spellInfo)
15021  {
15022  if (spellInfo->IsPassive())
15023  _unit->CastSpell(_unit, spellInfo, true);
15024  else
15025  AddSpellToActionBar(spellInfo, ACT_PASSIVE);
15026  }
15027  }
15028  }
15029  else
15031 }
15032 
15034 {
15035  InitPetActionBar();
15036 
15037  if (_unit->GetTypeId() == TYPEID_PLAYER) // charmed players don't have spells
15038  {
15039  //InitEmptyActionBar();
15040  return;
15041  }
15042 
15043  //InitPetActionBar();
15044 
15045  for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
15046  {
15047  uint32 spellId = _unit->ToCreature()->m_spells[x];
15048  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
15049 
15050  if (!spellInfo)
15051  {
15053  continue;
15054  }
15055 
15056  if (spellInfo->IsPassive())
15057  {
15058  _unit->CastSpell(_unit, spellInfo, true);
15060  }
15061  else
15062  {
15064 
15065  ActiveStates newstate = ACT_PASSIVE;
15066 
15067  if (!spellInfo->IsAutocastable())
15068  newstate = ACT_PASSIVE;
15069  else
15070  {
15071  if (spellInfo->NeedsExplicitUnitTarget())
15072  {
15073  newstate = ACT_ENABLED;
15074  ToggleCreatureAutocast(spellInfo, true);
15075  }
15076  else
15077  newstate = ACT_DISABLED;
15078  }
15079 
15080  AddSpellToActionBar(spellInfo, newstate);
15081  }
15082  }
15083 }
15084 
15086 {
15087  uint32 spell_id = spellInfo->Id;
15088  uint32 first_id = spellInfo->GetFirstRankSpell()->Id;
15089 
15090  // new spell rank can be already listed
15091  for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
15092  {
15093  if (uint32 action = PetActionBar[i].GetAction())
15094  {
15095  if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id)
15096  {
15097  PetActionBar[i].SetAction(spell_id);
15098  return true;
15099  }
15100  }
15101  }
15102 
15103  // or use empty slot in other case
15104  for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
15105  {
15106  if (!PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell())
15107  {
15108  SetActionBar(i, spell_id, newstate == ACT_DECIDE ? spellInfo->IsAutocastable() ? ACT_DISABLED : ACT_PASSIVE : newstate);
15109  return true;
15110  }
15111  }
15112  return false;
15113 }
15114 
15116 {
15117  uint32 first_id = sSpellMgr->GetFirstSpellInChain(spell_id);
15118 
15119  for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
15120  {
15121  if (uint32 action = PetActionBar[i].GetAction())
15122  {
15123  if (PetActionBar[i].IsActionBarForSpell() && sSpellMgr->GetFirstSpellInChain(action) == first_id)
15124  {
15125  SetActionBar(i, 0, ACT_PASSIVE);
15126  return true;
15127  }
15128  }
15129  }
15130 
15131  return false;
15132 }
15133 
15135 {
15136  if (spellInfo->IsPassive())
15137  return;
15138 
15139  for (uint32 x = 0; x < MAX_SPELL_CHARM; ++x)
15140  if (spellInfo->Id == _charmspells[x].GetAction())
15142 }
15143 
15144 void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow)
15145 {
15146  _petnumber = petnumber;
15147  if (statwindow)
15149  else
15151 }
15152 
15153 void CharmInfo::LoadPetActionBar(const std::string& data)
15154 {
15155  Tokenizer tokens(data, ' ');
15156 
15157  if (tokens.size() != (ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_START) * 2)
15158  return; // non critical, will reset to default
15159 
15161  Tokenizer::const_iterator iter = tokens.begin();
15162  for (; index < ACTION_BAR_INDEX_END; ++iter, ++index)
15163  {
15164  // use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
15165  ActiveStates type = ActiveStates(atol(*iter));
15166  ++iter;
15167  uint32 action = uint32(atol(*iter));
15168 
15170 
15171  // check correctness
15172  if (PetActionBar[index].IsActionBarForSpell())
15173  {
15174  SpellInfo const* spelInfo = sSpellMgr->GetSpellInfo(PetActionBar[index].GetAction());
15175  if (!spelInfo)
15177  else if (!spelInfo->IsAutocastable())
15179  }
15180  }
15181 }
15182 
15184 {
15185  for (uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
15186  *data << uint32(PetActionBar[i].packedData);
15187 }
15188 
15189 void CharmInfo::SetSpellAutocast(SpellInfo const* spellInfo, bool state)
15190 {
15191  for (uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
15192  {
15193  if (spellInfo->Id == PetActionBar[i].GetAction() && PetActionBar[i].IsActionBarForSpell())
15194  {
15196  break;
15197  }
15198  }
15199 }
15200 
15201 bool Unit::isFrozen() const
15202 {
15204 }
15205 
15207 {
15208  ProcTriggeredData(Aura* _aura) : aura(_aura)
15209  {
15210  effMask = 0;
15211  spellProcEvent = nullptr;
15212  triggerSpelId.fill(0);
15213  }
15214 
15218  std::array<uint32, EFFECT_ALL> triggerSpelId;
15219 
15220  bool operator==(const uint32 spellId) const
15221  {
15222  return aura->GetId() == spellId;
15223  }
15224 };
15225 
15226 typedef std::list< ProcTriggeredData > ProcTriggeredList;
15227 
15228 // List of auras that CAN be trigger but may not exist in spell_proc_event
15229 // in most case need for drop charges
15230 // in some types of aura need do additional check
15231 // for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic
15233 {
15234  for (uint16 i = 0; i < TOTAL_AURAS; ++i)
15235  {
15236  isTriggerAura[i] = false;
15237  isNonTriggerAura[i] = false;
15238  isAlwaysTriggeredAura[i] = false;
15239  }
15243  isTriggerAura[SPELL_AURA_MOD_STUN] = true; // Aura does not have charges but needs to be removed on trigger
15248  isTriggerAura[SPELL_AURA_MOD_FEAR] = true; // Aura does not have charges but needs to be removed on trigger
15256  isTriggerAura[SPELL_AURA_SCHOOL_ABSORB] = true; // Savage Defense untested
15276 
15279 
15288 
15289  return true;
15290 }
15291 
15292 void createProcFlags(const SpellInfo* spellInfo, WeaponAttackType attackType, bool positive, uint32& procAttacker, uint32& procVictim)
15293 {
15294  if (spellInfo)
15295  {
15296  switch (spellInfo->DmgClass)
15297  {
15299  if (positive)
15300  {
15303  }
15304  else
15305  {
15308  }
15309  break;
15311  if (positive)
15312  {
15315  }
15316  else
15317  {
15320  }
15321  break;
15323  procAttacker = PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS;
15324  if (attackType == OFF_ATTACK)
15325  procAttacker |= PROC_FLAG_DONE_OFFHAND_ATTACK;
15326  else
15327  procAttacker |= PROC_FLAG_DONE_MAINHAND_ATTACK;
15329  break;
15331  // Auto attack
15332  if (spellInfo->HasAttribute(SPELL_ATTR2_AUTO_REPEAT))
15333  {
15334  procAttacker = PROC_FLAG_DONE_RANGED_AUTO_ATTACK;
15336  }
15337  else // Ranged spell attack
15338  {
15341  }
15342  break;
15343  default:
15344  if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON &&
15346  && spellInfo->HasAttribute(SPELL_ATTR2_AUTO_REPEAT)) // Wands auto attack
15347  {
15348  procAttacker = PROC_FLAG_DONE_RANGED_AUTO_ATTACK;
15350  }
15351  break;
15352  }
15353  }
15354  else if (attackType == BASE_ATTACK)
15355  {
15357  procVictim = PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK;
15358  }
15359  else if (attackType == OFF_ATTACK)
15360  {
15362  procVictim = PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK;
15363  }
15364 }
15365 
15367 {
15368  uint32 procEx = PROC_EX_NONE;
15369  // Check victim state
15370  if (missCondition != SPELL_MISS_NONE)
15371  switch (missCondition)
15372  {
15373  case SPELL_MISS_MISS:
15374  procEx |= PROC_EX_MISS;
15375  break;
15376  case SPELL_MISS_RESIST:
15377  procEx |= PROC_EX_RESIST;
15378  break;
15379  case SPELL_MISS_DODGE:
15380  procEx |= PROC_EX_DODGE;
15381  break;
15382  case SPELL_MISS_PARRY:
15383  procEx |= PROC_EX_PARRY;
15384  break;
15385  case SPELL_MISS_BLOCK:
15386  procEx |= PROC_EX_BLOCK;
15387  break;
15388  case SPELL_MISS_EVADE:
15389  procEx |= PROC_EX_EVADE;
15390  break;
15391  case SPELL_MISS_IMMUNE:
15392  procEx |= PROC_EX_IMMUNE;
15393  break;
15394  case SPELL_MISS_IMMUNE2:
15395  procEx |= PROC_EX_IMMUNE;
15396  break;
15397  case SPELL_MISS_DEFLECT:
15398  procEx |= PROC_EX_DEFLECT;
15399  break;
15400  case SPELL_MISS_ABSORB:
15401  procEx |= PROC_EX_ABSORB;
15402  break;
15403  case SPELL_MISS_REFLECT:
15404  procEx |= PROC_EX_REFLECT;
15405  break;
15406  default:
15407  break;
15408  }
15409  else
15410  {
15411  // On block
15412  if (damageInfo->blocked)
15413  procEx |= PROC_EX_BLOCK;
15414  // On absorb
15415  if (damageInfo->absorb)
15416  procEx |= PROC_EX_ABSORB;
15417  // On crit
15418  if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
15419  procEx |= PROC_EX_CRITICAL_HIT;
15420  else
15421  procEx |= PROC_EX_NORMAL_HIT;
15422  }
15423  return procEx;
15424 }
15425 
15426 void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpellInfo, uint32 damage, SpellInfo const* procAura, int8 procAuraEffectIndex, Spell const* procSpell, DamageInfo* damageInfo, HealInfo* healInfo)
15427 {
15428  // Player is loaded now - do not allow passive spell casts to proc
15429  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetSession()->PlayerLoading())
15430  return;
15431  // For melee/ranged based attack need update skills and set some Aura states if victim present
15432  if (procFlag & MELEE_BASED_TRIGGER_MASK && target)
15433  {
15434  // Xinef: Shaman in ghost wolf form cant proc anything melee based
15435  if (!isVictim && GetShapeshiftForm() == FORM_GHOSTWOLF)
15436  return;
15437 
15438  // Update skills here for players
15439  // only when you are not fighting other players or their pets/totems (pvp)
15440  if (GetTypeId() == TYPEID_PLAYER &&
15441  target->GetTypeId() != TYPEID_PLAYER &&
15442  !(target->IsTotem() && target->ToTotem()->GetOwner()->IsPlayer()) &&
15443  !target->IsPet()
15444  )
15445  {
15446  // On melee based hit/miss/resist/parry/dodge need to update skill (for victim and attacker)
15448  {
15449  if (target->GetTypeId() != TYPEID_PLAYER)
15450  ToPlayer()->UpdateCombatSkills(target, attType, isVictim, procSpell ? procSpell->m_weaponItem : nullptr);
15451  }
15452  // Update defence if player is victim and we block
15453  else if (isVictim && procExtra & (PROC_EX_BLOCK))
15454  ToPlayer()->UpdateCombatSkills(target, attType, true);
15455  }
15456  // If exist crit/parry/dodge/block need update aura state (for victim and attacker)
15458  {
15459  // for victim
15460  if (isVictim)
15461  {
15462  // if victim and dodge attack
15463  if (procExtra & PROC_EX_DODGE)
15464  {
15465  // Update AURA_STATE on dodge
15466  if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
15467  {
15470  }
15471  }
15472  // if victim and parry attack
15473  if (procExtra & PROC_EX_PARRY)
15474  {
15475  // For Hunters only Counterattack (skip Mongoose bite)
15476  if (getClass() == CLASS_HUNTER)
15477  {
15480  }
15481  else
15482  {
15485  }
15486  }
15487  // if and victim block attack
15488  if (procExtra & PROC_EX_BLOCK)
15489  {
15492  }
15493  }
15494  else // For attacker
15495  {
15496  // Overpower on victim dodge
15497  if (procExtra & PROC_EX_DODGE )
15498  {
15499  if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
15500  {
15501  ToPlayer()->AddComboPoints(target, 1);
15503  }
15504  }
15505  // Wolverine Bite
15506  if (procExtra & PROC_EX_CRITICAL_HIT)
15507  {
15508  if (GetTypeId() == TYPEID_UNIT && IsPet())
15509  {
15512  }
15513  }
15514  }
15515  }
15516  }
15517 
15518  Unit* actor = isVictim ? target : this;
15519  Unit* actionTarget = !isVictim ? target : this;
15520 
15521  ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, procSpell, damageInfo, healInfo, procAura, procAuraEffectIndex);
15522 
15523  ProcTriggeredList procTriggered;
15524  // Fill procTriggered list
15525  for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
15526  {
15527  // Do not allow auras to proc from effect triggered by itself
15528  if (procAura && procAura->Id == itr->first)
15529  continue;
15530 
15531  // Xinef: Generic Item Equipment cooldown, -1 is a special marker
15532  if (itr->second->GetBase()->GetCastItemGUID() && HasSpellItemCooldown(itr->first, uint32(-1)))
15533  continue;
15534 
15535  ProcTriggeredData triggerData(itr->second->GetBase());
15536  // Defensive procs are active on absorbs (so absorption effects are not a hindrance)
15537  bool active = damage || (procExtra & PROC_EX_BLOCK && isVictim);
15538  if (isVictim)
15539  procExtra &= ~PROC_EX_INTERNAL_REQ_FAMILY;
15540 
15541  SpellInfo const* spellProto = itr->second->GetBase()->GetSpellInfo();
15542 
15543  // only auras that have trigger spell should proc from fully absorbed damage
15544  if (procExtra & PROC_EX_ABSORB && isVictim)
15545  if (damage || spellProto->Effects[EFFECT_0].TriggerSpell || spellProto->Effects[EFFECT_1].TriggerSpell || spellProto->Effects[EFFECT_2].TriggerSpell)
15546  active = true;
15547 
15548  // xinef: fix spell procing from damaging / healing casts if spell has DoT / HoT effect only
15549  // only player spells are taken into account
15550  if (!active && !isVictim && !(procFlag & PROC_FLAG_DONE_PERIODIC) && procSpellInfo && procSpellInfo->SpellFamilyName && (procSpellInfo->HasAura(SPELL_AURA_PERIODIC_DAMAGE) || procSpellInfo->HasAura(SPELL_AURA_PERIODIC_HEAL)))
15551  active = true;
15552 
15553  if (!IsTriggeredAtSpellProcEvent(target, triggerData.aura, attType, isVictim, active, triggerData.spellProcEvent, eventInfo))
15554  continue;
15555 
15556  // do checks using conditions table
15557  ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id);
15558  ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
15559  if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
15560  continue;
15561 
15562  // AuraScript Hook
15563  if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
15564  continue;
15565 
15566  // Triggered spells not triggering additional spells
15567  //bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_FROM_PROCS) ?
15568  // (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
15569 
15570  bool hasTriggeredProc = false;
15571  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
15572  {
15573  if (itr->second->HasEffect(i))
15574  {
15575  AuraEffect* aurEff = itr->second->GetBase()->GetEffect(i);
15576 
15577  // Skip this auras
15578  if (isNonTriggerAura[aurEff->GetAuraType()])
15579  continue;
15580 
15581  // If not trigger by default and spellProcEvent == nullptr - skip
15582  if (!isTriggerAura[aurEff->GetAuraType()] && triggerData.spellProcEvent == nullptr)
15583  continue;
15584 
15585  switch (aurEff->GetAuraType())
15586  {
15589  case SPELL_AURA_DUMMY:
15591  if (uint32 triggerSpellId = aurEff->GetSpellInfo()->Effects[i].TriggerSpell)
15592  {
15593  triggerData.triggerSpelId[i] = triggerSpellId;
15594  hasTriggeredProc = true;
15595  }
15596  break;
15597  default:
15598  break;
15599  }
15600 
15601  // Some spells must always trigger
15602  //if (isAlwaysTriggeredAura[aurEff->GetAuraType()])
15603  triggerData.effMask |= 1 << i;
15604  }
15605  }
15606 
15607  if (triggerData.effMask)
15608  {
15609  // If there is aura that triggers another proc aura, make sure that the triggered one is going to be proccessed on top of it
15610  if (hasTriggeredProc)
15611  {
15612  bool proccessed = false;
15613  for (uint8 i = 0; i < EFFECT_ALL; ++i)
15614  {
15615  if (uint32 triggeredSpellId = triggerData.triggerSpelId[i])
15616  {
15617  auto iter = std::find(procTriggered.begin(), procTriggered.end(), triggeredSpellId);
15618  if (iter != procTriggered.end())
15619  {
15620  std::advance(iter, 1);
15621  procTriggered.insert(iter, triggerData);
15622  proccessed = true;
15623  break;
15624  }
15625  }
15626  }
15627 
15628  if (!proccessed)
15629  {
15630  procTriggered.push_front(triggerData);
15631  }
15632  }
15633  else
15634  {
15635  procTriggered.push_front(triggerData);
15636  }
15637  }
15638  }
15639 
15640  // Nothing found
15641  if (procTriggered.empty())
15642  return;
15643 
15644  // Note: must SetCantProc(false) before return
15646  SetCantProc(true);
15647 
15648  // Handle effects proceed this time
15649  for (ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
15650  {
15651  // look for aura in auras list, it may be removed while proc event processing
15652  if (i->aura->IsRemoved())
15653  continue;
15654 
15655  bool useCharges = i->aura->IsUsingCharges();
15656  // no more charges to use, prevent proc
15657  if (useCharges && !i->aura->GetCharges())
15658  continue;
15659 
15660  bool takeCharges = false;
15661  SpellInfo const* spellInfo = i->aura->GetSpellInfo();
15662 
15663  AuraApplication* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
15664 
15665  bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
15666 
15667  // For players set spell cooldown if need
15668  uint32 cooldown = 0;
15669  if (prepare && i->spellProcEvent && i->spellProcEvent->cooldown)
15670  cooldown = i->spellProcEvent->cooldown;
15671 
15672  // Xinef: set cooldown for actual proc
15673  eventInfo.SetProcCooldown(cooldown);
15674 
15675  // Note: must SetCantProc(false) before return
15677  SetCantProc(true);
15678 
15679  bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo);
15680 
15681  // "handled" is needed as long as proc can be handled in multiple places
15682  if (!handled && HandleAuraProc(target, damage, i->aura, procSpellInfo, procFlag, procExtra, cooldown, &handled))
15683  {
15684  uint32 Id = i->aura->GetId();
15685  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), Id);
15686  takeCharges = true;
15687  }
15688 
15689  if (!handled)
15690  for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
15691  {
15692  if (!(i->effMask & (1 << effIndex)))
15693  continue;
15694 
15695  AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
15696  ASSERT(triggeredByAura);
15697 
15698  bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
15699  if (prevented)
15700  {
15701  takeCharges = true;
15702  continue;
15703  }
15704 
15705  switch(triggeredByAura->GetAuraType())
15706  {
15708  {
15709  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15710  // Don`t drop charge or add cooldown for not started trigger
15711  if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown))
15712  takeCharges = true;
15713  break;
15714  }
15716  {
15717  // target has to be valid
15718  if (!eventInfo.GetProcTarget())
15719  break;
15720 
15721  triggeredByAura->HandleProcTriggerDamageAuraProc(aurApp, eventInfo); // this function is part of the new proc system
15722  takeCharges = true;
15723  break;
15724  }
15726  case SPELL_AURA_DUMMY:
15727  {
15728  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15729  if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown))
15730  takeCharges = true;
15731  break;
15732  }
15737  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());
15738  takeCharges = true;
15739  break;
15741  {
15742  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15743  if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpellInfo, cooldown))
15744  takeCharges = true;
15745  break;
15746  }
15748  {
15749  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
15750  (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15751  if (damage > 0)
15752  {
15753  HandleAuraRaidProcFromChargeWithValue(triggeredByAura);
15754  takeCharges = true;
15755  }
15756  break;
15757  }
15759  {
15760  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
15761  (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15762  HandleAuraRaidProcFromCharge(triggeredByAura);
15763  takeCharges = true;
15764  break;
15765  }
15767  {
15768  LOG_DEBUG("spells.aura", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
15769 
15770  if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpellInfo, procFlag, procExtra, cooldown))
15771  takeCharges = true;
15772  break;
15773  }
15775  // Skip melee hits or instant cast spells
15776  // xinef: check channeled spells which are affected by haste also
15777  if (procSpellInfo && (procSpellInfo->SpellFamilyName || GetTypeId() != TYPEID_PLAYER) &&
15778  (procSpellInfo->CalcCastTime() > 0 /*||
15779  (procSpell->IsChanneled() && procSpell->GetDuration() > 0 && (HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, procSpell) || procSpell->HasAttribute(SPELL_ATTR5_SPELL_HASTE_AFFECTS_PERIODIC)))*/))
15780  takeCharges = true;
15781  break;
15783  // Skip Melee hits and spells ws wrong school
15784  if (procSpellInfo && (triggeredByAura->GetMiscValue() & procSpellInfo->SchoolMask)) // School check
15785  takeCharges = true;
15786  break;
15788  // Skip Melee hits and targets with magnet aura
15789  if (procSpellInfo && (triggeredByAura->GetBase()->GetUnitOwner()->ToUnit() == ToUnit())) // Magnet
15790  takeCharges = true;
15791  break;
15794  // Skip melee hits and spells ws wrong school or zero cost
15795  if (procSpellInfo &&
15796  (procSpellInfo->ManaCost != 0 || procSpellInfo->ManaCostPercentage != 0 || (procSpellInfo->SpellFamilyFlags[1] & 0x2)) && // Cost check, mutilate include
15797  (triggeredByAura->GetMiscValue() & procSpellInfo->SchoolMask)) // School check
15798  takeCharges = true;
15799  break;
15802  // Compare mechanic
15803  if (procSpellInfo && procSpellInfo->Mechanic == uint32(triggeredByAura->GetMiscValue()))
15804  takeCharges = true;
15805  break;
15807  // Compare casters
15808  if (target && triggeredByAura->GetCasterGUID() == target->GetGUID())
15809  takeCharges = true;
15810  break;
15811  // CC Auras which use their amount amount to drop
15812  // Are there any more auras which need this?
15814  case SPELL_AURA_MOD_FEAR:
15815  case SPELL_AURA_MOD_STUN:
15816  case SPELL_AURA_MOD_ROOT:
15817  case SPELL_AURA_TRANSFORM:
15818  {
15819  // Spell own direct damage at apply wont break the CC
15820  // Xinef: Or when the aura is at full duration (assume that such auras should be added at the end, skipping all damage procs etc.)
15821  if (procSpellInfo)
15822  if ((!i->aura->IsPermanent() && i->aura->GetDuration() == i->aura->GetMaxDuration()) || procSpellInfo->Id == triggeredByAura->GetId() ||
15824  break;
15825 
15826  // chargeable mods are breaking on hit
15827  if (useCharges)
15828  takeCharges = true;
15829  else if (triggeredByAura->GetAmount()) // aura must have amount
15830  {
15831  int32 damageLeft = triggeredByAura->GetAmount();
15832  // No damage left
15833  if (damageLeft < int32(damage))
15834  i->aura->Remove();
15835  else
15836  triggeredByAura->SetAmount(damageLeft - damage);
15837  }
15838  break;
15839  }
15841  if (procSpellInfo && procSpellInfo->Id == 20647) // hack for warriors execute, both dummy and damage spell are affected by ignore aurastate aura
15842  break;
15843  takeCharges = true;
15844  break;
15845  default:
15846  takeCharges = true;
15847  break;
15848  }
15849  i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
15850  }
15851  // Remove charge (aura can be removed by triggers)
15852  // xinef: take into account attribute6 of proc spell
15853  if (prepare && useCharges && takeCharges)
15854  if (!procSpellInfo || isVictim || !procSpellInfo->HasAttribute(SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES))
15855  i->aura->DropCharge();
15856 
15857  i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
15858 
15860  SetCantProc(false);
15861  }
15862 
15863  // Cleanup proc requirements
15865  SetCantProc(false);
15866 }
15867 
15868 void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo)
15869 {
15870  // use provided list of auras which can proc
15871  if (procAuras)
15872  {
15873  for (std::list<AuraApplication*>::iterator itr = procAuras->begin(); itr != procAuras->end(); ++itr)
15874  {
15875  ASSERT((*itr)->GetTarget() == this);
15876  if (!(*itr)->GetRemoveMode())
15877  if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo))
15878  {
15879  (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo);
15880  aurasTriggeringProc.push_back(*itr);
15881  }
15882  }
15883  }
15884  // or generate one on our own
15885  else
15886  {
15887  for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
15888  {
15889  if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo))
15890  {
15891  itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo);
15892  aurasTriggeringProc.push_back(itr->second);
15893  }
15894  }
15895  }
15896 }
15897 
15899 {
15900  DamageInfo dmgInfo = DamageInfo(damageInfo);
15901  TriggerAurasProcOnEvent(nullptr, nullptr, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, 0, 0, damageInfo.procEx, nullptr, &dmgInfo, nullptr);
15902 }
15903 
15904 void Unit::TriggerAurasProcOnEvent(std::list<AuraApplication*>* myProcAuras, std::list<AuraApplication*>* targetProcAuras, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
15905 {
15906  // prepare data for self trigger
15907  ProcEventInfo myProcEventInfo = ProcEventInfo(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
15908  std::list<AuraApplication*> myAurasTriggeringProc;
15909  GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, myProcAuras, myProcEventInfo);
15910 
15911  // prepare data for target trigger
15912  ProcEventInfo targetProcEventInfo = ProcEventInfo(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
15913  std::list<AuraApplication*> targetAurasTriggeringProc;
15914  if (typeMaskActionTarget)
15915  GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, targetProcAuras, targetProcEventInfo);
15916 
15917  TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
15918 
15919  if (typeMaskActionTarget)
15920  TriggerAurasProcOnEvent(targetProcEventInfo, targetAurasTriggeringProc);
15921 }
15922 
15923 void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, std::list<AuraApplication*>& aurasTriggeringProc)
15924 {
15925  for (std::list<AuraApplication*>::iterator itr = aurasTriggeringProc.begin(); itr != aurasTriggeringProc.end(); ++itr)
15926  {
15927  if (!(*itr)->GetRemoveMode())
15928  (*itr)->GetBase()->TriggerProcOnEvent(*itr, eventInfo);
15929  }
15930 }
15931 
15933 {
15934  return SPELL_SCHOOL_MASK_NORMAL;
15935 }
15936 
15938 {
15939  if (Player* player = const_cast<Unit*>(this)->ToPlayer())
15940  return player;
15941 
15942  if (Unit* owner = GetOwner())
15943  if (Player* player = owner->ToPlayer())
15944  return player;
15945 
15946  return nullptr;
15947 }
15948 
15951 {
15952  Unit* owner = GetOwner();
15953  if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
15954  return;
15955 
15957  data << uint8(msg);
15958  owner->ToPlayer()->GetSession()->SendPacket(&data);
15959 }
15960 
15962 {
15963  Unit* owner = GetOwner();
15964  if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
15965  return;
15966 
15968  data << GetGUID();
15969  data << uint32(pettalk);
15970  owner->ToPlayer()->GetSession()->SendPacket(&data);
15971 }
15972 
15974 {
15975  Unit* owner = GetOwner();
15976  if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
15977  return;
15978 
15980  data << guid;
15982  owner->ToPlayer()->GetSession()->SendPacket(&data);
15983 }
15984 
15986 
15988 {
15990 
15991  // not need send any packets if not in world or not moving
15992  if (!IsInWorld())
15993  return;
15994 
15995  if (movespline->Finalized())
15996  return;
15997 
15998  // Update position now since Stop does not start a new movement that can be updated later
15999  if (movespline->HasStarted())
16001 
16002  Movement::MoveSplineInit init(this);
16003  init.Stop();
16004 }
16005 
16006 void Unit::StopMovingOnCurrentPos() // pussywizard
16007 {
16009 
16010  // not need send any packets if not in world
16011  if (!IsInWorld())
16012  return;
16013 
16014  DisableSpline(); // pussywizard: required so Launch() won't recalculate position from previous spline
16015  Movement::MoveSplineInit init(this);
16017  init.SetFacing(GetOrientation());
16018  init.Launch();
16019 }
16020 
16021 void Unit::SendMovementFlagUpdate(bool self /* = false */)
16022 {
16023  WorldPacket data;
16025  SendMessageToSet(&data, self);
16026 }
16027 
16028 bool Unit::IsSitState() const
16029 {
16030  uint8 s = getStandState();
16031  return
16034  s == UNIT_STAND_STATE_SIT;
16035 }
16036 
16038 {
16039  uint8 s = getStandState();
16040  return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL;
16041 }
16042 
16044 {
16046 
16047  if (IsStandState())
16049 
16050  if (GetTypeId() == TYPEID_PLAYER)
16051  {
16053  data << (uint8)state;
16055  }
16056 }
16057 
16059 {
16060  uint32 transformId = getTransForm();
16061  if (!transformId)
16062  return false;
16063 
16064  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(transformId);
16065  if (!spellInfo)
16066  return false;
16067 
16068  return spellInfo->GetSpellSpecific() == SPELL_SPECIFIC_MAGE_POLYMORPH;
16069 }
16070 
16072 {
16074  // Set Gender by modelId
16075  if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
16076  SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
16077 }
16078 
16080 {
16081  AuraEffect* handledAura = nullptr;
16082  AuraEffect* handledAuraForced = nullptr;
16083  // try to receive model from transform auras
16085  if (!transforms.empty())
16086  {
16087  // iterate over already applied transform auras - from newest to oldest
16088  for (Unit::AuraEffectList::const_reverse_iterator i = transforms.rbegin(); i != transforms.rend(); ++i)
16089  {
16090  if (AuraApplication const* aurApp = (*i)->GetBase()->GetApplicationOfTarget(GetGUID()))
16091  {
16092  if (!handledAura)
16093  handledAura = (*i);
16094  // xinef: prefer negative/forced auras
16095  if ((*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) || !aurApp->IsPositive())
16096  {
16097  handledAuraForced = (*i);
16098  break;
16099  }
16100  }
16101  }
16102  }
16103 
16104  // Xinef: include clone auras (eg mirror images)
16105  if (!handledAuraForced && !handledAura)
16106  {
16108  if (!cloneAuras.empty())
16109  for (Unit::AuraEffectList::const_iterator i = cloneAuras.begin(); i != cloneAuras.end(); ++i)
16110  handledAura = *i;
16111  }
16112 
16113  // xinef: order of execution is important!
16114  // first forced transform auras, then shapeshifts, then normal transform
16115  // transform aura was found
16116  if (handledAuraForced)
16117  handledAuraForced->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true);
16118  // we've found shapeshift
16119  else if (uint32 modelId = GetModelForForm(GetShapeshiftForm()))
16120  SetDisplayId(modelId);
16121  else if (handledAura)
16122  handledAura->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true);
16123  // no auras found - set modelid to default
16124  else
16126 }
16127 
16129 {
16130  while (!m_ComboPointHolders.empty())
16131  {
16132  ObjectGuid guid = *m_ComboPointHolders.begin();
16133 
16134  Player* player = ObjectAccessor::GetPlayer(*this, guid);
16135  if (player && player->GetComboTarget() == GetGUID()) // recheck for safe
16136  player->ClearComboPoints(); // remove also guid from m_ComboPointHolders;
16137  else
16138  m_ComboPointHolders.erase(guid); // or remove manually
16139  }
16140 }
16141 
16143 {
16144  for (uint8 i = 0; i < MAX_REACTIVE; ++i)
16145  m_reactiveTimer[i] = 0;
16146 
16151  if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
16153 }
16154 
16156 {
16157  for (uint8 i = 0; i < MAX_REACTIVE; ++i)
16158  {
16159  ReactiveType reactive = ReactiveType(i);
16160 
16161  if (!m_reactiveTimer[reactive])
16162  continue;
16163 
16164  if (m_reactiveTimer[reactive] <= p_time)
16165  {
16166  m_reactiveTimer[reactive] = 0;
16167 
16168  switch (reactive)
16169  {
16170  case REACTIVE_DEFENSE:
16173  break;
16174  case REACTIVE_HUNTER_PARRY:
16177  break;
16178  case REACTIVE_OVERPOWER:
16179  if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
16181  break;
16182  default:
16183  break;
16184  }
16185  }
16186  else
16187  {
16188  m_reactiveTimer[reactive] -= p_time;
16189  }
16190  }
16191 }
16192 
16193 Unit* Unit::SelectNearbyTarget(Unit* exclude, float dist) const
16194 {
16195  std::list<Unit*> targets;
16196  Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, dist);
16198  Cell::VisitAllObjects(this, searcher, dist);
16199 
16200  // remove current target
16201  if (GetVictim())
16202  targets.remove(GetVictim());
16203 
16204  if (exclude)
16205  targets.remove(exclude);
16206 
16207  // remove not LoS targets
16208  for (std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end();)
16209  {
16210  if (!IsWithinLOSInMap(*tIter) || !IsValidAttackTarget(*tIter))
16211  {
16212  std::list<Unit*>::iterator tIter2 = tIter;
16213  ++tIter;
16214  targets.erase(tIter2);
16215  }
16216  else
16217  ++tIter;
16218  }
16219 
16220  // no appropriate targets
16221  if (targets.empty())
16222  return nullptr;
16223 
16224  // select random
16226 }
16227 
16228 Unit* Unit::SelectNearbyNoTotemTarget(Unit* exclude, float dist) const
16229 {
16230  std::list<Unit*> targets;
16231  Acore::AnyUnfriendlyNoTotemUnitInObjectRangeCheck u_check(this, this, dist);
16233  Cell::VisitAllObjects(this, searcher, dist);
16234 
16235  // remove current target
16236  if (GetVictim())
16237  targets.remove(GetVictim());
16238 
16239  if (exclude)
16240  targets.remove(exclude);
16241 
16242  // remove not LoS targets
16243  for (std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end();)
16244  {
16245  if (!IsWithinLOSInMap(*tIter) || !IsValidAttackTarget(*tIter))
16246  {
16247  std::list<Unit*>::iterator tIter2 = tIter;
16248  ++tIter;
16249  targets.erase(tIter2);
16250  }
16251  else
16252  ++tIter;
16253  }
16254 
16255  // no appropriate targets
16256  if (targets.empty())
16257  return nullptr;
16258 
16259  // select random
16261 }
16262 
16264 {
16265  float remainingTimePct = std::max((float)m_attackTimer[att], 0.0f) / (GetAttackTime(att) * m_modAttackSpeedPct[att]);
16266  if (val > 0)
16267  {
16270  }
16271  else
16272  {
16275  }
16276  m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct);
16277 }
16278 
16280 {
16281  if (val > 0)
16283  else
16285 }
16286 
16287 uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const
16288 {
16289  // Not apply this to creature casted spells with casttime == 0
16290  if (CastingTime == 0 && GetTypeId() == TYPEID_UNIT && !IsPet())
16291  return 3500;
16292 
16293  if (CastingTime > 7000) CastingTime = 7000;
16294  if (CastingTime < 1500) CastingTime = 1500;
16295 
16296  if (damagetype == DOT && !spellProto->IsChanneled())
16297  CastingTime = 3500;
16298 
16299  int32 overTime = 0;
16300  uint8 effects = 0;
16301  bool DirectDamage = false;
16302  bool AreaEffect = false;
16303 
16304  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; i++)
16305  {
16306  switch (spellProto->Effects[i].Effect)
16307  {
16313  case SPELL_EFFECT_HEAL:
16314  DirectDamage = true;
16315  break;
16317  switch (spellProto->Effects[i].ApplyAuraName)
16318  {
16322  if (spellProto->GetDuration())
16323  overTime = spellProto->GetDuration();
16324  break;
16325  default:
16326  // -5% per additional effect
16327  ++effects;
16328  break;
16329  }
16330  default:
16331  break;
16332  }
16333 
16334  if (spellProto->Effects[i].IsTargetingArea())
16335  AreaEffect = true;
16336  }
16337 
16338  // Combined Spells with Both Over Time and Direct Damage
16339  if (overTime > 0 && DirectDamage)
16340  {
16341  // mainly for DoTs which are 3500 here otherwise
16342  uint32 OriginalCastTime = spellProto->CalcCastTime();
16343  if (OriginalCastTime > 7000) OriginalCastTime = 7000;
16344  if (OriginalCastTime < 1500) OriginalCastTime = 1500;
16345  // Portion to Over Time
16346  float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f));
16347 
16348  if (damagetype == DOT)
16349  CastingTime = uint32(CastingTime * PtOT);
16350  else if (PtOT < 1.0f)
16351  CastingTime = uint32(CastingTime * (1 - PtOT));
16352  else
16353  CastingTime = 0;
16354  }
16355 
16356  // Area Effect Spells receive only half of bonus
16357  if (AreaEffect)
16358  CastingTime /= 2;
16359 
16360  // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
16361  for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
16362  {
16363  if (spellProto->Effects[j].Effect == SPELL_EFFECT_HEALTH_LEECH ||
16364  (spellProto->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && spellProto->Effects[j].ApplyAuraName == SPELL_AURA_PERIODIC_LEECH))
16365  {
16366  CastingTime /= 2;
16367  break;
16368  }
16369  }
16370 
16371  // -5% of total per any additional effect
16372  for (uint8 i = 0; i < effects; ++i)
16373  CastingTime *= 0.95f;
16374 
16375  return CastingTime;
16376 }
16377 
16379 {
16380  if (slot >= MAX_AURAS) // slot not found, return
16381  return;
16382  if (Player* player = ToPlayer())
16383  {
16384  if (player->GetGroup())
16385  {
16386  player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS);
16387  player->SetAuraUpdateMaskForRaid(slot);
16388  }
16389  }
16390  else if (GetTypeId() == TYPEID_UNIT && IsPet())
16391  {
16392  Pet* pet = ((Pet*)this);
16393  if (pet->isControlled())
16394  {
16395  Unit* owner = GetOwner();
16396  if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup())
16397  {
16399  pet->SetAuraUpdateMaskForRaid(slot);
16400  }
16401  }
16402  }
16403 }
16404 
16405 float Unit::CalculateDefaultCoefficient(SpellInfo const* spellInfo, DamageEffectType damagetype) const
16406 {
16407  // Damage over Time spells bonus calculation
16408  float DotFactor = 1.0f;
16409  if (damagetype == DOT)
16410  {
16411  int32 DotDuration = spellInfo->GetDuration();
16412  if (!spellInfo->IsChanneled() && DotDuration > 0)
16413  DotFactor = DotDuration / 15000.0f;
16414 
16415  if (uint32 DotTicks = spellInfo->GetMaxTicks())
16416  DotFactor /= DotTicks;
16417  }
16418 
16419  int32 CastingTime = spellInfo->IsChanneled() ? spellInfo->GetDuration() : spellInfo->CalcCastTime();
16420  // Distribute Damage over multiple effects, reduce by AoE
16421  CastingTime = GetCastingTimeForBonus(spellInfo, damagetype, CastingTime);
16422 
16423  // As wowwiki says: C = (Cast Time / 3.5)
16424  return (CastingTime / 3500.0f) * DotFactor;
16425 }
16426 
16427 float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
16428 {
16429  if (!normalized || GetTypeId() != TYPEID_PLAYER)
16430  return float(GetAttackTime(attType)) / 1000.0f;
16431 
16432  Item* Weapon = ToPlayer()->GetWeaponForAttack(attType, true);
16433  if (!Weapon)
16434  return 2.4f; // fist attack
16435 
16436  switch (Weapon->GetTemplate()->InventoryType)
16437  {
16438  case INVTYPE_2HWEAPON:
16439  return 3.3f;
16440  case INVTYPE_RANGED:
16441  case INVTYPE_RANGEDRIGHT:
16442  case INVTYPE_THROWN:
16443  return 2.8f;
16444  case INVTYPE_WEAPON:
16446  case INVTYPE_WEAPONOFFHAND:
16447  default:
16448  return Weapon->GetTemplate()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7f : 2.4f;
16449  }
16450 }
16451 
16453 {
16455 }
16456 
16457 void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuards)
16458 {
16460 
16461  if (!player || ((attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer))) || player->InBattleground()))
16462  return;
16463 
16464  // check if there any guards that should care about the contested flag on player
16465  if (lookForNearContestedGuards)
16466  {
16467  std::list<Unit*> targets;
16470  Cell::VisitAllObjects(this, searcher, MAX_AGGRO_RADIUS);
16471 
16472  // return if there are no contested guards found
16473  if (!targets.size())
16474  {
16475  return;
16476  }
16477  }
16478 
16479  player->SetContestedPvPTimer(30000);
16480  if (!player->HasUnitState(UNIT_STATE_ATTACK_PLAYER))
16481  {
16484  // call MoveInLineOfSight for nearby contested guards
16486  }
16488  {
16490  // call MoveInLineOfSight for nearby contested guards
16492  }
16493 }
16494 
16495 void Unit::AddPetAura(PetAura const* petSpell)
16496 {
16497  if (GetTypeId() != TYPEID_PLAYER)
16498  return;
16499 
16500  m_petAuras.insert(petSpell);
16501  if (Pet* pet = ToPlayer()->GetPet())
16502  pet->CastPetAura(petSpell);
16503  else if (Unit* charm = GetCharm())
16504  charm->CastPetAura(petSpell);
16505 }
16506 
16507 void Unit::RemovePetAura(PetAura const* petSpell)
16508 {
16509  if (GetTypeId() != TYPEID_PLAYER)
16510  return;
16511 
16512  m_petAuras.erase(petSpell);
16513  if (Pet* pet = ToPlayer()->GetPet())
16514  pet->RemoveAurasDueToSpell(petSpell->GetAura(pet->GetEntry()));
16515  if (Unit* charm = GetCharm())
16516  charm->RemoveAurasDueToSpell(petSpell->GetAura(charm->GetEntry()));
16517 }
16518 
16519 void Unit::CastPetAura(PetAura const* aura)
16520 {
16521  uint32 auraId = aura->GetAura(GetEntry());
16522  if (!auraId)
16523  return;
16524 
16525  if (auraId == 35696) // Demonic Knowledge
16526  {
16527  int32 basePoints = aura->GetDamage();
16528  CastCustomSpell(this, auraId, &basePoints, nullptr, nullptr, true);
16529  }
16530  else
16531  CastSpell(this, auraId, true);
16532 }
16533 
16534 bool Unit::IsPetAura(Aura const* aura)
16535 {
16536  Unit* owner = GetOwner();
16537 
16538  if (!owner || owner->GetTypeId() != TYPEID_PLAYER)
16539  return false;
16540 
16541  // if the owner has that pet aura, return true
16542  for (PetAuraSet::const_iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end(); ++itr)
16543  {
16544  if ((*itr)->GetAura(GetEntry()) == aura->GetId())
16545  return true;
16546  }
16547  return false;
16548 }
16549 
16550 Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget, uint32 spell_id)
16551 {
16552  if (GetTypeId() != TYPEID_PLAYER)
16553  return nullptr;
16554 
16555  Pet* pet = new Pet(ToPlayer(), HUNTER_PET);
16556 
16557  if (!pet->CreateBaseAtCreature(creatureTarget))
16558  {
16559  delete pet;
16560  return nullptr;
16561  }
16562 
16563  uint8 level = creatureTarget->getLevel() + 5 < getLevel() ? (getLevel() - 5) : creatureTarget->getLevel();
16564 
16565  InitTamedPet(pet, level, spell_id);
16566 
16567  return pet;
16568 }
16569 
16570 Pet* Unit::CreateTamedPetFrom(uint32 creatureEntry, uint32 spell_id)
16571 {
16572  if (GetTypeId() != TYPEID_PLAYER)
16573  return nullptr;
16574 
16575  CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry);
16576  if (!creatureInfo)
16577  return nullptr;
16578 
16579  Pet* pet = new Pet(ToPlayer(), HUNTER_PET);
16580 
16581  if (!pet->CreateBaseAtCreatureInfo(creatureInfo, this) || !InitTamedPet(pet, getLevel(), spell_id))
16582  {
16583  delete pet;
16584  return nullptr;
16585  }
16586 
16587  return pet;
16588 }
16589 
16590 bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
16591 {
16592  pet->SetCreatorGUID(GetGUID());
16593  pet->SetFaction(GetFaction());
16594  pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id);
16595 
16596  if (GetTypeId() == TYPEID_PLAYER)
16598 
16599  if (!pet->InitStatsForLevel(level))
16600  {
16601  LOG_ERROR("entities.unit", "Pet::InitStatsForLevel() failed for creature (Entry: %u)!", pet->GetEntry());
16602  return false;
16603  }
16604 
16605  pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true);
16606  // this enables pet details window (Shift+P)
16607  pet->InitPetCreateSpells();
16608  pet->SetFullHealth();
16609  return true;
16610 }
16611 
16612 bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent, ProcEventInfo const& eventInfo)
16613 {
16614  SpellInfo const* spellProto = aura->GetSpellInfo();
16615  SpellInfo const* procSpell = eventInfo.GetSpellInfo();
16616 
16617  // let the aura be handled by new proc system if it has new entry
16618  if (sSpellMgr->GetSpellProcEntry(spellProto->Id))
16619  return false;
16620 
16621  // Get proc Event Entry
16622  spellProcEvent = sSpellMgr->GetSpellProcEvent(spellProto->Id);
16623 
16624  // Get EventProcFlag
16625  uint32 EventProcFlag;
16626  if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags
16627  EventProcFlag = spellProcEvent->procFlags;
16628  else
16629  EventProcFlag = spellProto->ProcFlags; // else get from spell proto
16630  // Continue if no trigger exist
16631  if (!EventProcFlag)
16632  return false;
16633 
16634  // Additional checks for triggered spells (ignore trap casts)
16635  //if (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION))
16636  //{
16637  // if (!spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_TRIGGERED))
16638  // return false;
16639  //}
16640 
16641  // Xinef: additional check for player auras - only player spells can trigger player proc auras
16642  // Xinef: skip victim auras
16643  // Excluded player shoot spells
16644  if (!isVictim && GetTypeId() == TYPEID_PLAYER) //spellProto->SpellFamilyName != SPELLFAMILY_GENERIC)
16645  if (!(EventProcFlag & (PROC_FLAG_KILL | PROC_FLAG_DEATH)) && procSpell && procSpell->SpellFamilyName == SPELLFAMILY_GENERIC && procSpell->GetCategory() != 76 &&
16647  return false;
16648 
16649  // Check spellProcEvent data requirements
16650  if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellProto, spellProcEvent, EventProcFlag, eventInfo, active))
16651  return false;
16652  // In most cases req get honor or XP from kill
16653  if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER)
16654  {
16655  bool allow = false;
16656 
16657  if (victim)
16658  allow = ToPlayer()->isHonorOrXPTarget(victim);
16659 
16660  // Shadow Word: Death - can trigger from every kill
16661  if (aura->GetId() == 32409 || aura->GetId() == 18372 || aura->GetId() == 18213)
16662  allow = true;
16663  if (!allow)
16664  return false;
16665  }
16666  // Aura added by spell can`t trigger from self (prevent drop charges/do triggers)
16667  // But except periodic and kill triggers (can triggered from self)
16668  if (procSpell && procSpell->Id == spellProto->Id
16669  && !(spellProto->ProcFlags & (PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL)))
16670  return false;
16671 
16672  // Check if current equipment allows aura to proc
16673  if (!isVictim && GetTypeId() == TYPEID_PLAYER && !spellProto->HasAttribute(SPELL_ATTR3_NO_PROC_EQUIP_REQUIREMENT))
16674  {
16675  Player* player = ToPlayer();
16676  if (spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)
16677  {
16678  Item* item = nullptr;
16679  if (attType == BASE_ATTACK)
16681  else if (attType == OFF_ATTACK)
16683  else
16685 
16686  if (player->IsInFeralForm())
16687  return false;
16688 
16689  if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1 << item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask))
16690  return false;
16691  }
16692  else if (spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)
16693  {
16694  // Check if player is wearing shield
16696  if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1 << item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask))
16697  return false;
16698  }
16699  }
16700  // Get chance from spell
16701  float chance = float(spellProto->ProcChance);
16702  // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;
16703  if (spellProcEvent && spellProcEvent->customChance)
16704  chance = spellProcEvent->customChance;
16705  // If PPM exist calculate chance from PPM
16706  if (spellProcEvent && spellProcEvent->ppmRate != 0)
16707  {
16708  if (!isVictim)
16709  {
16710  uint32 WeaponSpeed = GetAttackTime(attType);
16711  chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto);
16712  }
16713  else if (victim)
16714  {
16715  uint32 WeaponSpeed = victim->GetAttackTime(attType);
16716  chance = victim->GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto);
16717  }
16718  }
16719 
16720  // Custom chances
16721  switch (spellProto->SpellFamilyName)
16722  {
16723  case SPELLFAMILY_WARRIOR:
16724  {
16725  // Recklessness, allow to proc only once for whirlwind
16726  if (spellProto->Id == 1719 && procSpell && procSpell->Id == 44949)
16727  return false;
16728  }
16729  }
16730 
16731  // Apply chance modifer aura
16732  if (Player* modOwner = GetSpellModOwner())
16733  {
16734  modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance);
16735  }
16736  return roll_chance_f(chance);
16737 }
16738 
16740 {
16741  // aura can be deleted at casts
16742  SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
16743  int32 heal = triggeredByAura->GetAmount();
16744  ObjectGuid caster_guid = triggeredByAura->GetCasterGUID();
16745 
16746  // Currently only Prayer of Mending
16747  if (!(spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && spellProto->SpellFamilyFlags[1] & 0x20))
16748  {
16749  LOG_DEBUG("spells.aura", "Unit::HandleAuraRaidProcFromChargeWithValue, received not handled spell: %u", spellProto->Id);
16750  return false;
16751  }
16752 
16753  // jumps
16754  int32 jumps = triggeredByAura->GetBase()->GetCharges() - 1;
16755 
16756  // current aura expire
16757  triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
16758 
16759  // next target selection
16760  if (jumps > 0)
16761  {
16762  if (Unit* caster = triggeredByAura->GetCaster())
16763  {
16764  // smart healing
16765  float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
16766  std::list<Unit*> nearMembers;
16767 
16768  Player* player = nullptr;
16769  if (GetTypeId() == TYPEID_PLAYER)
16770  player = ToPlayer();
16771  else if (GetOwner())
16772  player = GetOwner()->ToPlayer();
16773 
16774  if (player)
16775  {
16776  Group* group = player->GetGroup();
16777  if (!group)
16778  {
16779  if (player != this)
16780  {
16781  if (IsWithinDistInMap(player, radius))
16782  nearMembers.push_back(player);
16783  }
16784  else if (Unit* pet = GetGuardianPet())
16785  {
16786  if (IsWithinDistInMap(pet, radius))
16787  nearMembers.push_back(pet);
16788  }
16789  }
16790  else
16791  {
16792  for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
16793  if (Player* Target = itr->GetSource())
16794  {
16795  if (Target != this && !IsWithinDistInMap(Target, radius))
16796  continue;
16797 
16798  // IsHostileTo check duel and controlled by enemy
16799  if (Target != this && Target->IsAlive() && !IsHostileTo(Target))
16800  nearMembers.push_back(Target);
16801 
16802  // Push player's pet to vector
16803  if (Unit* pet = Target->GetGuardianPet())
16804  if (pet != this && pet->IsAlive() && IsWithinDistInMap(pet, radius) && !IsHostileTo(pet))
16805  nearMembers.push_back(pet);
16806  }
16807  }
16808 
16809  if (!nearMembers.empty())
16810  {
16811  nearMembers.sort(Acore::HealthPctOrderPred());
16812  if (Unit* target = nearMembers.front())
16813  {
16814  CastSpell(target, 41637 /*Dummy visual effect triggered by main spell cast*/, true);
16815  CastCustomSpell(target, spellProto->Id, &heal, nullptr, nullptr, true, nullptr, triggeredByAura, caster_guid);
16816  if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
16817  aura->SetCharges(jumps);
16818  }
16819  }
16820  }
16821  }
16822  }
16823 
16824  // heal
16825  CastCustomSpell(this, 33110, &heal, nullptr, nullptr, true, nullptr, nullptr, caster_guid);
16826  return true;
16827 }
16829 {
16830  // aura can be deleted at casts
16831  SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
16832 
16833  uint32 damageSpellId;
16834  switch (spellProto->Id)
16835  {
16836  case 57949: // shiver
16837  damageSpellId = 57952;
16838  //animationSpellId = 57951; dummy effects for jump spell have unknown use (see also 41637)
16839  break;
16840  case 59978: // shiver
16841  damageSpellId = 59979;
16842  break;
16843  case 43593: // Cold Stare
16844  damageSpellId = 43594;
16845  break;
16846  default:
16847  LOG_ERROR("entities.unit", "Unit::HandleAuraRaidProcFromCharge, received unhandled spell: %u", spellProto->Id);
16848  return false;
16849  }
16850 
16851  ObjectGuid caster_guid = triggeredByAura->GetCasterGUID();
16852 
16853  // jumps
16854  int32 jumps = triggeredByAura->GetBase()->GetCharges() - 1;
16855 
16856  // current aura expire
16857  triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
16858 
16859  // next target selection
16860  if (jumps > 0)
16861  {
16862  if (Unit* caster = triggeredByAura->GetCaster())
16863  {
16864  float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
16865  if (Unit* target = GetNextRandomRaidMemberOrPet(radius))
16866  {
16867  CastSpell(target, spellProto, true, nullptr, triggeredByAura, caster_guid);
16868  if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
16869  aura->SetCharges(jumps);
16870  }
16871  }
16872  }
16873 
16874  CastSpell(this, damageSpellId, true, nullptr, triggeredByAura, caster_guid);
16875 
16876  return true;
16877 }
16878 
16879 void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackType attackType, SpellInfo const* spellProto)
16880 {
16881  // Prevent killing unit twice (and giving reward from kill twice)
16882  if (!victim->GetHealth())
16883  return;
16884 
16885  if (killer && !killer->IsInMap(victim))
16886  killer = nullptr;
16887 
16888  // find player: owner of controlled `this` or `this` itself maybe
16889  Player* player = killer ? killer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr;
16890  Creature* creature = victim->ToCreature();
16891 
16892  bool isRewardAllowed = true;
16893  if (creature)
16894  {
16895  isRewardAllowed = creature->IsDamageEnoughForLootingAndReward();
16896  if (!isRewardAllowed)
16897  creature->SetLootRecipient(nullptr);
16898  }
16899 
16900  // pussywizard: remade this if section (player is on the same map
16901  if (isRewardAllowed && creature)
16902  {
16903  Player* lr = creature->GetLootRecipient();
16904  if (lr && lr->IsInMap(creature))
16905  player = creature->GetLootRecipient();
16906  else if (Group* lrg = creature->GetLootRecipientGroup())
16907  for (GroupReference* itr = lrg->GetFirstMember(); itr != nullptr; itr = itr->next())
16908  if (Player* member = itr->GetSource())
16909  if (member->IsAtLootRewardDistance(creature))
16910  {
16911  player = member;
16912  break;
16913  }
16914  }
16915 
16916  // Exploit fix
16917  if (creature && creature->IsPet() && creature->GetOwnerGUID().IsPlayer())
16918  isRewardAllowed = false;
16919 
16920  // Reward player, his pets, and group/raid members
16921  // call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop)
16922  if (isRewardAllowed && player && player != victim)
16923  {
16924  WorldPacket data(SMSG_PARTYKILLLOG, (8 + 8)); // send event PARTY_KILL
16925  data << player->GetGUID(); // player with killing blow
16926  data << victim->GetGUID(); // victim
16927 
16928  Player* looter = player;
16929  Group* group = player->GetGroup();
16930  bool hasLooterGuid = false;
16931 
16932  if (group)
16933  {
16934  group->BroadcastPacket(&data, group->GetMemberGroup(player->GetGUID()));
16935 
16936  if (creature)
16937  {
16938  group->UpdateLooterGuid(creature, true);
16939  if (group->GetLooterGuid() && group->GetLootMethod() != FREE_FOR_ALL)
16940  {
16941  looter = ObjectAccessor::FindPlayer(group->GetLooterGuid());
16942  if (looter)
16943  {
16944  hasLooterGuid = true;
16945  creature->SetLootRecipient(looter); // update creature loot recipient to the allowed looter.
16946  }
16947  }
16948  }
16949  }
16950  else
16951  {
16952  player->SendDirectMessage(&data);
16953 
16954  if (creature)
16955  {
16956  WorldPacket data2(SMSG_LOOT_LIST, 8 + 1 + 1);
16957  data2 << creature->GetGUID();
16958  data2 << uint8(0); // unk1
16959  data2 << uint8(0); // no group looter
16960  player->SendMessageToSet(&data2, true);
16961  }
16962  }
16963 
16964  // Generate loot before updating looter
16965  if (creature)
16966  {
16967  Loot* loot = &creature->loot;
16968  loot->clear();
16969 
16970  if (uint32 lootid = creature->GetCreatureTemplate()->lootid)
16971  loot->FillLoot(lootid, LootTemplates_Creature, looter, false, false, creature->GetLootMode(), creature);
16972 
16973  if (creature->GetLootMode())
16974  loot->generateMoneyLoot(creature->GetCreatureTemplate()->mingold, creature->GetCreatureTemplate()->maxgold);
16975 
16976  if (group)
16977  {
16978  if (hasLooterGuid)
16979  group->SendLooter(creature, looter);
16980  else
16981  group->SendLooter(creature, nullptr);
16982 
16983  // Update round robin looter only if the creature had loot
16984  if (!creature->loot.empty())
16985  group->UpdateLooterGuid(creature);
16986  }
16987  }
16988 
16989  player->RewardPlayerAndGroupAtKill(victim, false);
16990  }
16991 
16992  // Do KILL and KILLED procs. KILL proc is called only for the unit who landed the killing blow (and its owner - for pets and totems) regardless of who tapped the victim
16993  if (killer && (killer->IsPet() || killer->IsTotem()))
16994  if (Unit* owner = killer->GetOwner())
16995  {
16996  owner->ProcDamageAndSpell(victim, PROC_FLAG_KILL, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto);
16997  sScriptMgr->OnCreatureKilledByPet( killer->GetCharmerOrOwnerPlayerOrPlayerItself(), victim->ToCreature());
16998  }
16999 
17000  if (killer != victim && !victim->IsCritter())
17001  killer->ProcDamageAndSpell(victim, killer ? PROC_FLAG_KILL : 0, PROC_FLAG_KILLED, PROC_EX_NONE, 0, attackType, spellProto);
17002 
17003  // Proc auras on death - must be before aura/combat remove
17004  victim->ProcDamageAndSpell(nullptr, PROC_FLAG_DEATH, PROC_FLAG_NONE, PROC_EX_NONE, 0, attackType, spellProto);
17005 
17006  // update get killing blow achievements, must be done before setDeathState to be able to require auras on target
17007  // and before Spirit of Redemption as it also removes auras
17008  if (killer)
17009  if (Player* killerPlayer = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
17010  killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, victim);
17011 
17012  // Spirit of Redemption
17013  // if talent known but not triggered (check priest class for speedup check)
17014  bool spiritOfRedemption = false;
17015  if (victim->GetTypeId() == TYPEID_PLAYER && victim->getClass() == CLASS_PRIEST)
17016  {
17017  if (AuraEffect* aurEff = victim->GetAuraEffectDummy(20711))
17018  {
17019  // Xinef: aura_spirit_of_redemption is triggered by 27827 shapeshift
17020  if (victim->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION) || victim->HasAura(27827))
17021  {
17022  /*LOG_INFO("misc", "Player (%s) died with spirit of redemption. Killer (Entry: %u, Name: %s), Map: %u, x: %f, y: %f, z: %f",
17023  victim->GetGUID().ToString().c_str(), killer ? killer->GetEntry() : 1, killer ? killer->GetName().c_str() : "", victim->GetMapId(), victim->GetPositionX(),
17024  victim->GetPositionY(), victim->GetPositionZ());
17025 
17026  ACE_Stack_Trace trace(0, 50);
17027  LOG_INFO("misc", "TRACE: %s\n\n", trace.c_str());*/
17028  }
17029  else
17030  {
17031  // save value before aura remove
17032  uint32 ressSpellId = victim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
17033  if (!ressSpellId)
17034  ressSpellId = victim->ToPlayer()->GetResurrectionSpellId();
17035 
17036  //Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
17037  victim->RemoveAllAurasOnDeath();
17038 
17039  // Stop attacks
17040  victim->CombatStop();
17041  victim->getHostileRefMgr().deleteReferences();
17042 
17043  // restore for use at real death
17044  victim->SetUInt32Value(PLAYER_SELF_RES_SPELL, ressSpellId);
17045 
17046  // FORM_SPIRITOFREDEMPTION and related auras
17047  victim->CastSpell(victim, 27827, true, nullptr, aurEff);
17048  spiritOfRedemption = true;
17049  }
17050  }
17051  }
17052 
17053  if (!spiritOfRedemption)
17054  {
17055  LOG_DEBUG("entities.unit", "SET JUST_DIED");
17056  victim->setDeathState(JUST_DIED);
17057  }
17058 
17059  // Inform pets (if any) when player kills target)
17060  // MUST come after victim->setDeathState(JUST_DIED); or pet next target
17061  // selection will get stuck on same target and break pet react state
17062  if (player)
17063  {
17064  Pet* pet = player->GetPet();
17065  if (pet && pet->IsAlive() && pet->isControlled())
17066  pet->AI()->KilledUnit(victim);
17067  }
17068 
17069  // 10% durability loss on death
17070  // clean InHateListOf
17071  if (Player* plrVictim = victim->ToPlayer())
17072  {
17073  // remember victim PvP death for corpse type and corpse reclaim delay
17074  // at original death (not at SpiritOfRedemtionTalent timeout)
17075  plrVictim->SetPvPDeath(player != nullptr);
17076 
17077  // only if not player and not controlled by player pet. And not at BG
17078  if ((durabilityLoss && !player && !plrVictim->InBattleground()) || (player && sWorld->getBoolConfig(CONFIG_DURABILITY_LOSS_IN_PVP)))
17079  {
17080  LOG_DEBUG("entities.unit", "We are dead, losing %f percent durability", sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH));
17081  plrVictim->DurabilityLossAll(sWorld->getRate(RATE_DURABILITY_LOSS_ON_DEATH), false);
17082  // durability lost message
17084  plrVictim->GetSession()->SendPacket(&data);
17085  }
17086  // Call KilledUnit for creatures
17087  if (killer && killer->GetTypeId() == TYPEID_UNIT && killer->IsAIEnabled)
17088  killer->ToCreature()->AI()->KilledUnit(victim);
17089 
17090  // last damage from non duel opponent or opponent controlled creature
17091  if (plrVictim->duel)
17092  {
17093  plrVictim->duel->opponent->CombatStopWithPets(true);
17094  plrVictim->CombatStopWithPets(true);
17095  plrVictim->DuelComplete(DUEL_INTERRUPTED);
17096  }
17097  }
17098  else // creature died
17099  {
17100  LOG_DEBUG("entities.unit", "DealDamageNotPlayer");
17101 
17102  if (!creature->IsPet() && creature->GetLootMode() > 0)
17103  {
17104  creature->DeleteThreatList();
17105  CreatureTemplate const* cInfo = creature->GetCreatureTemplate();
17106  if (cInfo && (cInfo->lootid || cInfo->maxgold > 0))
17108  }
17109 
17110  // Call KilledUnit for creatures, this needs to be called after the lootable flag is set
17111  if (killer && killer->GetTypeId() == TYPEID_UNIT && killer->IsAIEnabled)
17112  killer->ToCreature()->AI()->KilledUnit(victim);
17113 
17114  // Call creature just died function
17115  if (creature->IsAIEnabled)
17116  creature->AI()->JustDied(killer ? killer : victim);
17117 
17118  if (TempSummon* summon = creature->ToTempSummon())
17119  if (Unit* summoner = summon->GetSummonerUnit())
17120  if (summoner->ToCreature() && summoner->IsAIEnabled)
17121  summoner->ToCreature()->AI()->SummonedCreatureDies(creature, killer);
17122 
17123  // Dungeon specific stuff, only applies to players killing creatures
17124  if (creature->GetInstanceId())
17125  {
17126  Map* instanceMap = creature->GetMap();
17127  //Player* creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself();
17128  // TODO: do instance binding anyway if the charmer/owner is offline
17129 
17130  if (instanceMap->IsDungeon() && player)
17131  if (instanceMap->IsRaidOrHeroicDungeon())
17133  instanceMap->ToInstanceMap()->PermBindAllPlayers();
17134  }
17135  }
17136 
17137  // outdoor pvp things, do these after setting the death state, else the player activity notify won't work... doh...
17138  // handle player kill only if not suicide (spirit of redemption for example)
17139  if (player && killer != victim)
17140  {
17141  if (OutdoorPvP* pvp = player->GetOutdoorPvP())
17142  pvp->HandleKill(player, victim);
17143 
17144  if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetZoneId()))
17145  bf->HandleKill(player, victim);
17146  }
17147 
17148  //if (victim->GetTypeId() == TYPEID_PLAYER)
17149  // if (OutdoorPvP* pvp = victim->ToPlayer()->GetOutdoorPvP())
17150  // pvp->HandlePlayerActivityChangedpVictim->ToPlayer();
17151 
17152  // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
17153  if (player)
17154  if (Battleground* bg = player->GetBattleground())
17155  {
17156  if (victim->GetTypeId() == TYPEID_PLAYER)
17157  bg->HandleKillPlayer(victim->ToPlayer(), player);
17158  else
17159  bg->HandleKillUnit(victim->ToCreature(), player);
17160  }
17161 
17162  // achievement stuff
17163  if (killer && victim->GetTypeId() == TYPEID_PLAYER)
17164  {
17165  if (killer->GetTypeId() == TYPEID_UNIT)
17167  else if (victim != killer && killer->GetTypeId() == TYPEID_PLAYER)
17169  }
17170 
17171  // Hook for OnPVPKill Event
17172  if (killer)
17173  {
17174  if (Player* killerPlr = killer->ToPlayer())
17175  {
17176  if (Player* killedPlr = victim->ToPlayer())
17177  sScriptMgr->OnPVPKill(killerPlr, killedPlr);
17178  else if (Creature* killedCre = victim->ToCreature())
17179  sScriptMgr->OnCreatureKill(killerPlr, killedCre);
17180  }
17181  else if (Creature* killerCre = killer->ToCreature())
17182  {
17183  if (Player* killed = victim->ToPlayer())
17184  sScriptMgr->OnPlayerKilledByCreature(killerCre, killed);
17185  }
17186  }
17187 }
17188 
17190 {
17191  if (apply)
17192  {
17193  if (HasUnitState(state))
17194  return;
17195 
17196  AddUnitState(state);
17197  switch (state)
17198  {
17199  case UNIT_STATE_STUNNED:
17200  SetStunned(true);
17201  break;
17202  case UNIT_STATE_ROOT:
17204  SetRooted(true);
17205  break;
17206  case UNIT_STATE_CONFUSED:
17208  {
17211  // SendAutoRepeatCancel ?
17212  SetConfused(true);
17213  CastStop(0, false);
17214  }
17215  break;
17216  case UNIT_STATE_FLEEING:
17218  {
17221  // SendAutoRepeatCancel ?
17222  SetFeared(true);
17223  CastStop(0, false);
17224  }
17225  break;
17226  default:
17227  break;
17228  }
17229 
17230  if (GetTypeId() == TYPEID_PLAYER)
17231  {
17232  sScriptMgr->AnticheatSetRootACKUpd(ToPlayer());
17233  }
17234  }
17235  else
17236  {
17237  // xinef: moved from below, checked all SetX functions, no calls to currently modified state
17238  // xinef: added to each case because of return
17239  //ClearUnitState(state);
17240 
17241  switch (state)
17242  {
17243  case UNIT_STATE_STUNNED:
17245  return;
17246  ClearUnitState(state);
17247  SetStunned(false);
17248  break;
17249  case UNIT_STATE_ROOT:
17251  return;
17252  ClearUnitState(state);
17253  SetRooted(false);
17254  break;
17255  case UNIT_STATE_CONFUSED:
17257  return;
17258  ClearUnitState(state);
17259  SetConfused(false);
17260  break;
17261  case UNIT_STATE_FLEEING:
17263  return;
17264  ClearUnitState(state);
17265  SetFeared(false);
17266  break;
17267  default:
17268  return;
17269  }
17270 
17271  //ClearUnitState(state);
17272 
17274  SetStunned(true);
17275  else
17276  {
17278  SetRooted(true);
17279 
17281  SetConfused(true);
17283  SetFeared(true);
17284  }
17285  }
17286 }
17287 
17289 {
17290  if (apply)
17291  {
17292  SetTarget();
17294 
17295  if (GetTypeId() == TYPEID_PLAYER)
17296  {
17298  }
17299 
17300  SetRooted(true);
17301 
17302  CastStop();
17303  }
17304  else
17305  {
17306  if (IsAlive() && GetVictim())
17307  SetTarget(GetVictim()->GetGUID());
17308 
17309  if (GetTypeId() == TYPEID_UNIT)
17310  {
17311  // don't remove UNIT_FLAG_STUNNED for pet when owner is mounted (disabled pet's interface)
17312  Unit* owner = GetOwner();
17313  if (!owner || owner->GetTypeId() != TYPEID_PLAYER || !owner->ToPlayer()->IsMounted())
17315 
17316  // Xinef: same for charmed npcs
17317  owner = GetCharmer();
17318  if (!owner || owner->GetTypeId() != TYPEID_PLAYER || !owner->ToPlayer()->IsMounted())
17320  }
17321  else
17323 
17324  if (!HasUnitState(UNIT_STATE_ROOT)) // prevent moving if it also has root effect
17325  {
17326  SetRooted(false);
17327  }
17328  }
17329 }
17330 
17332 {
17333  if (apply)
17334  {
17335  if (m_rootTimes > 0) // blizzard internal check?
17336  m_rootTimes++;
17337 
17338  // MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
17339  // this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
17340  // setting MOVEMENTFLAG_ROOT
17342 
17343  if (IsFalling())
17344  {
17346  }
17347  else
17348  {
17350  }
17351 
17352  // Creature specific
17353  if (GetTypeId() != TYPEID_PLAYER)
17354  {
17355  StopMoving();
17356  }
17357 
17358  if (m_movedByPlayer)
17359  {
17361  data << GetPackGUID();
17362  data << m_rootTimes;
17364  }
17365  else
17366  {
17368  data << GetPackGUID();
17369  SendMessageToSet(&data, true);
17370  }
17371  }
17372  else
17373  {
17375 
17376  if (!HasUnitState(UNIT_STATE_STUNNED)) // prevent moving if it also has stun effect
17377  {
17378  if (m_movedByPlayer)
17379  {
17381  data << GetPackGUID();
17382  data << m_rootTimes;
17384  }
17385  else
17386  {
17388  data << GetPackGUID();
17389  SendMessageToSet(&data, true);
17390  }
17391  }
17392  }
17393 }
17394 
17396 {
17397  if (GetTypeId() != TYPEID_UNIT)
17398  return;
17399 
17400  if (apply)
17404 }
17405 
17407 {
17408  if (apply)
17409  {
17410  SetTarget();
17411 
17412  Unit* caster = nullptr;
17414  if (!fearAuras.empty())
17415  caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID());
17416  if (!caster)
17417  caster = getAttackerForHelper();
17418  GetMotionMaster()->MoveFleeing(caster, fearAuras.empty() ? sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY) : 0); // caster == nullptr processed in MoveFleeing
17419 
17420  if (GetTypeId() == TYPEID_PLAYER)
17421  {
17422  sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
17423  }
17424  }
17425  else
17426  {
17427  if (IsAlive())
17428  {
17429  if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == FLEEING_MOTION_TYPE)
17430  {
17432  StopMoving();
17433  }
17434 
17435  if (GetVictim())
17436  SetTarget(GetVictim()->GetGUID());
17437  }
17438  }
17439 
17440  // xinef: block / allow control to real mover (eg. charmer)
17441  if (GetTypeId() == TYPEID_PLAYER)
17442  {
17443  if (m_movedByPlayer)
17444  m_movedByPlayer->ToPlayer()->SetClientControl(this, !apply); // verified
17445  //else
17446  // ToPlayer()->SetClientControl(this, !apply);
17447  }
17448 }
17449 
17451 {
17452  if (apply)
17453  {
17454  SetTarget();
17456 
17457  if (GetTypeId() == TYPEID_PLAYER)
17458  {
17459  sScriptMgr->AnticheatSetSkipOnePacketForASH(ToPlayer(), true);
17460  }
17461  }
17462  else
17463  {
17464  if (IsAlive())
17465  {
17466  if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == CONFUSED_MOTION_TYPE)
17467  {
17469  StopMoving();
17470  }
17471 
17472  if (GetVictim())
17473  SetTarget(GetVictim()->GetGUID());
17474  }
17475  }
17476 
17477  // xinef: block / allow control to real mover (eg. charmer)
17478  if (GetTypeId() == TYPEID_PLAYER)
17479  {
17480  if (m_movedByPlayer)
17481  m_movedByPlayer->ToPlayer()->SetClientControl(this, !apply); // verified
17482  //else
17483  // ToPlayer()->SetClientControl(this, !apply);
17484  }
17485 }
17486 
17487 bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* aurApp)
17488 {
17489  if (!charmer)
17490  return false;
17491 
17492  if (!charmer->IsInWorld() || charmer->IsDuringRemoveFromWorld())
17493  {
17494  return false;
17495  }
17496 
17497  // dismount players when charmed
17498  if (GetTypeId() == TYPEID_PLAYER)
17500 
17501  if (charmer->GetTypeId() == TYPEID_PLAYER)
17503 
17504  ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
17505  if (type == CHARM_TYPE_VEHICLE && !IsVehicle()) // pussywizard
17506  throw 1;
17508 
17509  LOG_DEBUG("entities.unit", "SetCharmedBy: charmer %u (%s), charmed %u (%s), type %u.",
17510  charmer->GetEntry(), charmer->GetGUID().ToString().c_str(), GetEntry(), GetGUID().ToString().c_str(), uint32(type));
17511 
17512  if (this == charmer)
17513  {
17514  LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Unit %u (%s) is trying to charm itself!", GetEntry(), GetGUID().ToString().c_str());
17515  return false;
17516  }
17517 
17518  //if (HasUnitState(UNIT_STATE_UNATTACKABLE))
17519  // return false;
17520 
17521  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetTransport())
17522  {
17523  LOG_FATAL("entities.unit", "Unit::SetCharmedBy: Player on transport is trying to charm %u (%s)", GetEntry(), GetGUID().ToString().c_str());
17524  return false;
17525  }
17526 
17527  // Already charmed
17528  if (GetCharmerGUID())
17529  {
17530  LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (%s) has already been charmed but %u (%s) is trying to charm it!",
17531  GetEntry(), GetGUID().ToString().c_str(), charmer->GetEntry(), charmer->GetGUID().ToString().c_str());
17532  return false;
17533  }
17534 
17535  CastStop();
17536  AttackStop();
17537 
17538  // Xinef: dont reset threat and combat, put them on offline list, moved down after faction changes
17539  // CombatStop(); // TODO: CombatStop(true) may cause crash (interrupt spells)
17540  // DeleteThreatList();
17541 
17542  Player* playerCharmer = charmer->ToPlayer();
17543 
17544  // Charmer stop charming
17545  if (playerCharmer)
17546  {
17547  playerCharmer->StopCastingCharm();
17548  playerCharmer->StopCastingBindSight();
17549  }
17550 
17551  // Charmed stop charming
17552  if (GetTypeId() == TYPEID_PLAYER)
17553  {
17556  }
17557 
17558  // StopCastingCharm may remove a possessed pet?
17559  if (!IsInWorld())
17560  {
17561  LOG_FATAL("entities.unit", "Unit::SetCharmedBy: %u (%s) is not in world but %u (%s) is trying to charm it!",
17562  GetEntry(), GetGUID().ToString().c_str(), charmer->GetEntry(), charmer->GetGUID().ToString().c_str());
17563  return false;
17564  }
17565 
17566  // charm is set by aura, and aura effect remove handler was called during apply handler execution
17567  // prevent undefined behaviour
17568  if (aurApp && aurApp->GetRemoveMode())
17569  return false;
17570 
17572  SetFaction(charmer->GetFaction());
17573 
17574  // Set charmed
17575  charmer->SetCharm(this, true);
17576 
17577  if (GetTypeId() == TYPEID_UNIT)
17578  {
17579  ToCreature()->AI()->OnCharmed(true);
17581 
17582  // Xinef: If creature can fly, add normal player flying flag (fixes speed)
17583  if (charmer->GetTypeId() == TYPEID_PLAYER && ToCreature()->CanFly())
17585  }
17586  else
17587  {
17588  Player* player = ToPlayer();
17589  if (player->isAFK())
17590  player->ToggleAFK();
17591 
17592  player->SetClientControl(this, false); // verified
17593  }
17594 
17595  // charm is set by aura, and aura effect remove handler was called during apply handler execution
17596  // prevent undefined behaviour
17597  if (aurApp && aurApp->GetRemoveMode())
17598  return false;
17599 
17600  // Pets already have a properly initialized CharmInfo, don't overwrite it.
17601  // Xinef: I need charmInfo for vehicle so bullshit
17602  if (/*type != CHARM_TYPE_VEHICLE &&*/ !GetCharmInfo())
17603  {
17604  InitCharmInfo();
17605  if (type == CHARM_TYPE_POSSESS)
17607  else if (type != CHARM_TYPE_VEHICLE)
17608  {
17610 
17611  // Xinef: convert charm npcs dont have pet bar so initialize them as defensive helpers
17614  }
17615  }
17616 
17617  if (playerCharmer)
17618  {
17619  switch (type)
17620  {
17621  case CHARM_TYPE_VEHICLE:
17624  playerCharmer->SetClientControl(this, true); // verified
17625  playerCharmer->VehicleSpellInitialize();
17626  break;
17627  case CHARM_TYPE_POSSESS:
17632  playerCharmer->SetClientControl(this, true); // verified
17633  playerCharmer->PossessSpellInitialize();
17634  break;
17635  case CHARM_TYPE_CHARM:
17636  if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
17637  {
17638  CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
17639  if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
17640  {
17641  // to prevent client crash
17643 
17644  // just to enable stat window
17645  if (GetCharmInfo())
17646  GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true);
17647 
17648  // if charmed two demons the same session, the 2nd gets the 1st one's name
17649  SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr))); // cast can't be helped
17650  }
17651  }
17653  playerCharmer->CharmSpellInitialize();
17654  break;
17655  default:
17656  break;
17657  }
17658  }
17659  else if (GetTypeId() == TYPEID_PLAYER)
17661 
17662  if (Creature* creature = ToCreature())
17663  creature->RefreshSwimmingFlag();
17664 
17665  if (GetTypeId() == TYPEID_PLAYER)
17666  sScriptMgr->OnPlayerBeingCharmed(ToPlayer(), charmer, _oldFactionId, charmer->GetFaction());
17667 
17668  return true;
17669 }
17670 
17672 {
17673  if (!IsCharmed())
17674  return;
17675 
17676  if (!charmer)
17677  charmer = GetCharmer();
17678  if (charmer != GetCharmer()) // one aura overrides another?
17679  {
17680  // LOG_FATAL("entities.unit", "Unit::RemoveCharmedBy: this: %s true charmer: %s false charmer: %s",
17681  // GetGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), charmer->GetGUID().ToString().c_str());
17682  // ABORT();
17683  return;
17684  }
17685 
17686  CharmType type;
17689  else if (charmer && charmer->IsOnVehicle(this))
17691  else
17693 
17694  if (_oldFactionId)
17695  {
17697  _oldFactionId = 0;
17698  }
17699  else
17700  RestoreFaction();
17701 
17702  CastStop();
17703  AttackStop();
17704 
17705  // xinef: update speed after charming
17706  UpdateSpeed(MOVE_RUN, false);
17707 
17708  // xinef: do not break any controlled motion slot
17709  if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
17710  {
17711  StopMoving();
17713  }
17714  // xinef: if we have any controlled movement, clear active and idle only
17715  else
17717 
17719 
17720  // xinef: remove stunned flag if owner was mounted
17723 
17724  // If charmer still exists
17725  if (!charmer)
17726  return;
17727 
17728  ASSERT(type != CHARM_TYPE_POSSESS || charmer->GetTypeId() == TYPEID_PLAYER);
17730 
17731  charmer->SetCharm(this, false);
17732 
17733  Player* playerCharmer = charmer->ToPlayer();
17734  if (playerCharmer)
17735  {
17736  switch (type)
17737  {
17738  case CHARM_TYPE_VEHICLE:
17739  playerCharmer->SetClientControl(this, false);
17740  playerCharmer->SetClientControl(charmer, true); // verified
17743  break;
17744  case CHARM_TYPE_POSSESS:
17745  playerCharmer->SetClientControl(this, false);
17746  playerCharmer->SetClientControl(charmer, true); // verified
17751  break;
17752  case CHARM_TYPE_CHARM:
17753  if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
17754  {
17755  CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
17756  if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
17757  {
17759  if (GetCharmInfo())
17760  GetCharmInfo()->SetPetNumber(0, true);
17761  else
17762  LOG_ERROR("entities.unit", "Aura::HandleModCharm: target=%s has a charm aura but no charm info!", GetGUID().ToString().c_str());
17763  }
17764  }
17765  break;
17766  default:
17767  break;
17768  }
17769  }
17770 
17771  if (Player* player = ToPlayer())
17772  {
17773  sScriptMgr->AnticheatSetUnderACKmount(player);
17774  }
17775 
17776  // xinef: restore threat
17777  for (CharmThreatMap::const_iterator itr = _charmThreatInfo.begin(); itr != _charmThreatInfo.end(); ++itr)
17778  {
17779  if (Unit* target = ObjectAccessor::GetUnit(*this, itr->first))
17780  if (!IsFriendlyTo(target))
17781  AddThreat(target, itr->second);
17782  }
17783 
17784  _charmThreatInfo.clear();
17785 
17786  if (Creature* creature = ToCreature())
17787  {
17788  // Vehicle should not attack its passenger after he exists the seat
17789  if (type != CHARM_TYPE_VEHICLE && charmer->IsAlive() && !charmer->IsFriendlyTo(creature))
17790  if (Attack(charmer, true))
17791  GetMotionMaster()->MoveChase(charmer);
17792 
17793  // Creature will restore its old AI on next update
17794  if (creature->AI())
17795  creature->AI()->OnCharmed(false);
17796 
17797  // Xinef: Remove movement flag flying
17799  }
17800  else
17801  ToPlayer()->SetClientControl(this, true); // verified
17802 
17803  // a guardian should always have charminfo
17804  if (playerCharmer && this != charmer->GetFirstControlled())
17805  playerCharmer->SendRemoveControlBar();
17806 
17807  // xinef: Always delete charm info (restores react state)
17808  if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && !ToCreature()->IsGuardian()))
17809  DeleteCharmInfo();
17810 }
17811 
17813 {
17814  if (GetTypeId() == TYPEID_PLAYER)
17816  else
17817  {
17819  {
17820  if (Unit* owner = GetOwner())
17821  {
17822  SetFaction(owner->GetFaction());
17823  return;
17824  }
17825  }
17826 
17827  if (CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate()) // normal creature
17828  SetFaction(cinfo->faction);
17829  }
17830 }
17831 
17832 bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry)
17833 {
17834  VehicleEntry const* vehInfo = sVehicleStore.LookupEntry(id);
17835  if (!vehInfo)
17836  return false;
17837 
17838  m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
17841  return true;
17842 }
17843 
17845 {
17846  if (!m_vehicleKit)
17847  return;
17848 
17850  delete m_vehicleKit;
17851 
17852  m_vehicleKit = nullptr;
17853 
17857 }
17858 
17860 {
17861  return m_vehicle ? m_vehicle->GetBase() : nullptr;
17862 }
17863 
17865 {
17866  if (Unit* veh = GetVehicleBase())
17867  if (Creature* c = veh->ToCreature())
17868  return c;
17869 
17870  return nullptr;
17871 }
17872 
17874 {
17875  if (GetVehicle())
17876  return GetVehicleBase()->GetGUID();
17877 
17878  if (GetTransport())
17879  return GetTransport()->GetGUID();
17880 
17881  return ObjectGuid::Empty;
17882 }
17883 
17885 {
17886  if (Vehicle* veh = GetVehicle())
17887  return veh;
17888  return GetTransport();
17889 }
17890 
17891 bool Unit::IsInPartyWith(Unit const* unit) const
17892 {
17893  if (this == unit)
17894  return true;
17895 
17896  const Unit* u1 = GetCharmerOrOwnerOrSelf();
17897  const Unit* u2 = unit->GetCharmerOrOwnerOrSelf();
17898  if (u1 == u2)
17899  return true;
17900 
17901  if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
17902  return u1->ToPlayer()->IsInSameGroupWith(u2->ToPlayer());
17903  // Xinef: we assume that npcs with the same faction are in party
17904  else if (u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && !u1->IsControlledByPlayer() && !u2->IsControlledByPlayer())
17905  return u1->GetFaction() == u2->GetFaction();
17906  // Xinef: creature type_flag should work for party check only if player group is not a raid
17909  return true;
17910  else
17911  return false;
17912 }
17913 
17914 bool Unit::IsInRaidWith(Unit const* unit) const
17915 {
17916  if (this == unit)
17917  return true;
17918 
17919  const Unit* u1 = GetCharmerOrOwnerOrSelf();
17920  const Unit* u2 = unit->GetCharmerOrOwnerOrSelf();
17921  if (u1 == u2)
17922  return true;
17923 
17924  if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER)
17925  return u1->ToPlayer()->IsInSameRaidWith(u2->ToPlayer());
17926  // Xinef: we assume that npcs with the same faction are in party
17927  else if (u1->GetTypeId() == TYPEID_UNIT && u2->GetTypeId() == TYPEID_UNIT && !u1->IsControlledByPlayer() && !u2->IsControlledByPlayer())
17928  return u1->GetFaction() == u2->GetFaction();
17931  return true;
17932  else
17933  return false;
17934 }
17935 
17936 void Unit::GetPartyMembers(std::list<Unit*>& TagUnitMap)
17937 {
17938  Unit* owner = GetCharmerOrOwnerOrSelf();
17939  Group* group = nullptr;
17940  if (owner->GetTypeId() == TYPEID_PLAYER)
17941  group = owner->ToPlayer()->GetGroup();
17942 
17943  if (group)
17944  {
17945  uint8 subgroup = owner->ToPlayer()->GetSubGroup();
17946 
17947  for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
17948  {
17949  Player* Target = itr->GetSource();
17950 
17951  // IsHostileTo check duel and controlled by enemy
17952  if (Target && Target->IsInMap(owner) && Target->GetSubGroup() == subgroup && !IsHostileTo(Target))
17953  {
17954  if (Target->IsAlive())
17955  TagUnitMap.push_back(Target);
17956 
17957  for (Unit::ControlSet::iterator iterator = Target->m_Controlled.begin(); iterator != Target->m_Controlled.end(); ++iterator)
17958  {
17959  if (Unit* pet = *iterator)
17960  if (pet->IsGuardian() && pet->IsAlive())
17961  TagUnitMap.push_back(pet);
17962  }
17963  }
17964  }
17965  }
17966  else
17967  {
17968  if (owner->IsAlive())
17969  TagUnitMap.push_back(owner);
17970 
17971  for (Unit::ControlSet::iterator itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end(); ++itr)
17972  {
17973  if (Unit* pet = *itr)
17974  if (pet->IsGuardian() && pet->IsAlive())
17975  TagUnitMap.push_back(pet);
17976  }
17977  }
17978 }
17979 
17980 Aura* Unit::AddAura(uint32 spellId, Unit* target)
17981 {
17982  if (!target)
17983  return nullptr;
17984 
17985  SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
17986  if (!spellInfo)
17987  return nullptr;
17988 
17989  if (!target->IsAlive() && !spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) && !spellInfo->HasAttribute(SPELL_ATTR2_ALLOW_DEAD_TARGET))
17990  return nullptr;
17991 
17992  return AddAura(spellInfo, MAX_EFFECT_MASK, target);
17993 }
17994 
17995 Aura* Unit::AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target)
17996 {
17997  if (!spellInfo)
17998  return nullptr;
17999 
18000  if (target->IsImmunedToSpell(spellInfo))
18001  return nullptr;
18002 
18003  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
18004  {
18005  if (!(effMask & (1 << i)))
18006  continue;
18007  if (target->IsImmunedToSpellEffect(spellInfo, i))
18008  effMask &= ~(1 << i);
18009  }
18010 
18011  if (Aura* aura = Aura::TryRefreshStackOrCreate(spellInfo, effMask, target, this))
18012  {
18013  aura->ApplyForTargets();
18014  return aura;
18015  }
18016  return nullptr;
18017 }
18018 
18019 void Unit::SetAuraStack(uint32 spellId, Unit* target, uint32 stack)
18020 {
18021  Aura* aura = target->GetAura(spellId, GetGUID());
18022  if (!aura)
18023  aura = AddAura(spellId, target);
18024  if (aura && stack)
18025  aura->SetStackAmount(stack);
18026 }
18027 
18029 {
18031  data << GetGUID();
18032  data << uint32(id); // SpellVisualKit.dbc index
18033  SendMessageToSet(&data, true);
18034 }
18035 
18037 {
18039  data << guid; // target
18040  data << uint32(id); // SpellVisualKit.dbc index
18041  SendMessageToSet(&data, true);
18042 }
18043 
18044 void Unit::ApplyResilience(Unit const* victim, float* crit, int32* damage, bool isCrit, CombatRating type)
18045 {
18046  // player mounted on multi-passenger mount is also classified as vehicle
18047  if (victim->IsVehicle() && victim->GetTypeId() != TYPEID_PLAYER)
18048  return;
18049 
18050  Unit const* target = nullptr;
18051  if (victim->GetTypeId() == TYPEID_PLAYER)
18052  target = victim;
18053  else if (victim->GetTypeId() == TYPEID_UNIT)
18054  {
18055  if (Unit* owner = victim->GetOwner())
18056  if (owner->GetTypeId() == TYPEID_PLAYER)
18057  target = owner;
18058  }
18059 
18060  if (!target)
18061  return;
18062 
18063  switch (type)
18064  {
18065  case CR_CRIT_TAKEN_MELEE:
18066  // Crit chance reduction works against nonpets
18067  if (crit)
18068  *crit -= target->GetMeleeCritChanceReduction();
18069  if (damage)
18070  {
18071  if (isCrit)
18072  *damage -= target->GetMeleeCritDamageReduction(*damage);
18073  *damage -= target->GetMeleeDamageReduction(*damage);
18074  }
18075  break;
18076  case CR_CRIT_TAKEN_RANGED:
18077  // Crit chance reduction works against nonpets
18078  if (crit)
18079  *crit -= target->GetRangedCritChanceReduction();
18080  if (damage)
18081  {
18082  if (isCrit)
18083  *damage -= target->GetRangedCritDamageReduction(*damage);
18084  *damage -= target->GetRangedDamageReduction(*damage);
18085  }
18086  break;
18087  case CR_CRIT_TAKEN_SPELL:
18088  // Crit chance reduction works against nonpets
18089  if (crit)
18090  *crit -= target->GetSpellCritChanceReduction();
18091  if (damage)
18092  {
18093  if (isCrit)
18094  *damage -= target->GetSpellCritDamageReduction(*damage);
18095  *damage -= target->GetSpellDamageReduction(*damage);
18096  }
18097  break;
18098  default:
18099  break;
18100  }
18101 }
18102 
18103 // Melee based spells can be miss, parry or dodge on this step
18104 // Crit or block - determined on damage calculation phase! (and can be both in some time)
18105 float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
18106 {
18107  SpellInfo const* spellInfo = spellId ? sSpellMgr->GetSpellInfo(spellId) : nullptr;
18108  if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR7_NO_ATTACK_MISS))
18109  {
18110  return 0.0f;
18111  }
18112 
18113  //calculate miss chance
18114  float missChance = victim->GetUnitMissChance(attType);
18115 
18116  if (!spellId && haveOffhandWeapon())
18117  missChance += 19;
18118 
18119  // bonus from skills is 0.04%
18120  //miss_chance -= skillDiff * 0.04f;
18121  int32 diff = -skillDiff;
18122  if (victim->GetTypeId() == TYPEID_PLAYER)
18123  missChance += diff > 0 ? diff * 0.04f : diff * 0.02f;
18124  else
18125  missChance += diff > 10 ? 1 + (diff - 10) * 0.4f : diff * 0.1f;
18126 
18127  // Calculate hit chance
18128  float hitChance = 100.0f;
18129 
18130  // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
18131  if (spellId)
18132  {
18133  if (Player* modOwner = GetSpellModOwner())
18134  modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, hitChance);
18135  }
18136 
18137  missChance += hitChance - 100.0f;
18138 
18139  if (attType == RANGED_ATTACK)
18140  missChance -= m_modRangedHitChance;
18141  else
18142  missChance -= m_modMeleeHitChance;
18143 
18144  // Limit miss chance from 0 to 60%
18145  if (missChance < 0.0f)
18146  return 0.0f;
18147  if (missChance > 60.0f)
18148  return 60.0f;
18149  return missChance;
18150 }
18151 
18153 {
18154  uint32 currentPhase = 0;
18156  if (!phases.empty())
18157  for (AuraEffectList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
18158  currentPhase |= (*itr)->GetMiscValue();
18159 
18160  return currentPhase;
18161 }
18162 
18163 void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
18164 {
18165  if (newPhaseMask == GetPhaseMask())
18166  return;
18167 
18168  if (IsInWorld())
18169  {
18170  // xinef: ZOMG!, to comment, bellow line should be removed
18171  // pussywizard: goign to other phase (valithria, algalon) should not remove such auras
18172  //RemoveNotOwnSingleTargetAuras(newPhaseMask, true); // we can lost access to caster or target
18173 
18174  if (!sScriptMgr->CanSetPhaseMask(this, newPhaseMask, update))
18175  return;
18176 
18177  // modify hostile references for new phasemask, some special cases deal with hostile references themselves
18178  if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout()))
18179  {
18180  HostileRefMgr& refMgr = getHostileRefMgr();
18181  HostileReference* ref = refMgr.getFirst();
18182 
18183  while (ref)
18184  {
18185  if (Unit* unit = ref->GetSource()->GetOwner())
18186  if (Creature* creature = unit->ToCreature())
18187  refMgr.setOnlineOfflineState(creature, creature->InSamePhase(newPhaseMask));
18188 
18189  ref = ref->next();
18190  }
18191 
18192  // modify threat lists for new phasemask
18193  if (GetTypeId() != TYPEID_PLAYER)
18194  {
18197 
18198  // merge expects sorted lists
18199  threatList.sort();
18200  offlineThreatList.sort();
18201  threatList.merge(offlineThreatList);
18202 
18203  for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
18204  if (Unit* unit = (*itr)->getTarget())
18205  unit->getHostileRefMgr().setOnlineOfflineState(ToCreature(), unit->InSamePhase(newPhaseMask));
18206  }
18207  }
18208  }
18209 
18210  WorldObject::SetPhaseMask(newPhaseMask, update);
18211 
18212  if (!IsInWorld())
18213  return;
18214 
18215  for (ControlSet::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); )
18216  {
18217  Unit* controlled = *itr;
18218  ++itr;
18219  if (controlled->GetTypeId() == TYPEID_UNIT)
18220  controlled->SetPhaseMask(newPhaseMask, true);
18221  }
18222 
18223  for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
18224  if (m_SummonSlot[i])
18225  if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i]))
18226  summon->SetPhaseMask(newPhaseMask, true);
18227 }
18228 
18229 void Unit::UpdateObjectVisibility(bool forced, bool /*fromUpdate*/)
18230 {
18231  if (!forced)
18233  else
18234  {
18236  Acore::AIRelocationNotifier notifier(*this);
18237  float radius = 60.0f;
18238  Cell::VisitAllObjects(this, notifier, radius);
18239  }
18240 }
18241 
18242 void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
18243 {
18244  Player* player = ToPlayer();
18245  if (!player)
18246  {
18247  if (Unit* charmer = GetCharmer())
18248  {
18249  player = charmer->ToPlayer();
18250  if (player && player->m_mover != this)
18251  player = nullptr;
18252  }
18253  }
18254 
18255  if (!player)
18256  {
18257  GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
18258  }
18259  else
18260  {
18261  float vcos, vsin;
18262  GetSinCos(x, y, vsin, vcos);
18263 
18264  WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8 + 4 + 4 + 4 + 4 + 4));
18265  data << GetPackGUID();
18266  data << uint32(0); // counter
18267  data << float(vcos); // x direction
18268  data << float(vsin); // y direction
18269  data << float(speedXY); // Horizontal speed
18270  data << float(-speedZ); // Z Movement speed (vertical)
18271 
18272  player->GetSession()->SendPacket(&data);
18273 
18275  player->SetCanFly(true, true);
18276 
18277  sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
18278  }
18279 }
18280 
18282 {
18283  if (Player const* player = ToPlayer())
18284  return player->GetRatingBonusValue(cr);
18285  // Player's pet get resilience from owner
18286  else if (IsPet() && GetOwner())
18287  if (Player* owner = GetOwner()->ToPlayer())
18288  return owner->GetRatingBonusValue(cr);
18289 
18290  return 0.0f;
18291 }
18292 
18293 uint32 Unit::GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const
18294 {
18295  float percent = std::min(GetCombatRatingReduction(cr) * rate, cap);
18296  return CalculatePct(damage, percent);
18297 }
18298 
18300 {
18301  if (GetTypeId() == TYPEID_PLAYER)
18302  {
18303  switch (form)
18304  {
18305  case FORM_CAT:
18306  // Based on Hair color
18307  if (getRace() == RACE_NIGHTELF)
18308  {
18309  uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
18310  switch (hairColor)
18311  {
18312  case 7: // Violet
18313  case 8:
18314  return 29405;
18315  case 3: // Light Blue
18316  return 29406;
18317  case 0: // Green
18318  case 1: // Light Green
18319  case 2: // Dark Green
18320  return 29407;
18321  case 4: // White
18322  return 29408;
18323  default: // original - Dark Blue
18324  return 892;
18325  }
18326  }
18327  // Based on Skin color
18328  else if (getRace() == RACE_TAUREN)
18329  {
18330  uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
18331  // Male
18332  if (getGender() == GENDER_MALE)
18333  {
18334  switch (skinColor)
18335  {
18336  case 12: // White
18337  case 13:
18338  case 14:
18339  case 18: // Completly White
18340  return 29409;
18341  case 9: // Light Brown
18342  case 10:
18343  case 11:
18344  return 29410;
18345  case 6: // Brown
18346  case 7:
18347  case 8:
18348  return 29411;
18349  case 0: // Dark
18350  case 1:
18351  case 2:
18352  case 3: // Dark Grey
18353  case 4:
18354  case 5:
18355  return 29412;
18356  default: // original - Grey
18357  return 8571;
18358  }
18359  }
18360  // Female
18361  else switch (skinColor)
18362  {
18363  case 10: // White
18364  return 29409;
18365  case 6: // Light Brown
18366  case 7:
18367  return 29410;
18368  case 4: // Brown
18369  case 5:
18370  return 29411;
18371  case 0: // Dark
18372  case 1:
18373  case 2:
18374  case 3:
18375  return 29412;
18376  default: // original - Grey
18377  return 8571;
18378  }
18379  }
18381  return 892;
18382  else
18383  return 8571;
18384  case FORM_DIREBEAR:
18385  case FORM_BEAR:
18386  // Based on Hair color
18387  if (getRace() == RACE_NIGHTELF)
18388  {
18389  uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
18390  switch (hairColor)
18391  {
18392  case 0: // Green
18393  case 1: // Light Green
18394  case 2: // Dark Green
18395  return 29413; // 29415?
18396  case 6: // Dark Blue
18397  return 29414;
18398  case 4: // White
18399  return 29416;
18400  case 3: // Light Blue
18401  return 29417;
18402  default: // original - Violet
18403  return 2281;
18404  }
18405  }
18406  // Based on Skin color
18407  else if (getRace() == RACE_TAUREN)
18408  {
18409  uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
18410  // Male
18411  if (getGender() == GENDER_MALE)
18412  {
18413  switch (skinColor)
18414  {
18415  case 0: // Dark (Black)
18416  case 1:
18417  case 2:
18418  return 29418;
18419  case 3: // White
18420  case 4:
18421  case 5:
18422  case 12:
18423  case 13:
18424  case 14:
18425  return 29419;
18426  case 9: // Light Brown/Grey
18427  case 10:
18428  case 11:
18429  case 15:
18430  case 16:
18431  case 17:
18432  return 29420;
18433  case 18: // Completly White
18434  return 29421;
18435  default: // original - Brown
18436  return 2289;
18437  }
18438  }
18439  // Female
18440  else switch (skinColor)
18441  {
18442  case 0: // Dark (Black)
18443  case 1:
18444  return 29418;
18445  case 2: // White
18446  case 3:
18447  return 29419;
18448  case 6: // Light Brown/Grey
18449  case 7:
18450  case 8:
18451  case 9:
18452  return 29420;
18453  case 10: // Completly White
18454  return 29421;
18455  default: // original - Brown
18456  return 2289;
18457  }
18458  }
18460  return 2281;
18461  else
18462  return 2289;
18463  case FORM_FLIGHT:
18465  return 20857;
18466  return 20872;
18467  case FORM_FLIGHT_EPIC:
18469  return 21243;
18470  return 21244;
18471  default:
18472  break;
18473  }
18474  }
18475 
18476  uint32 modelid = 0;
18477  SpellShapeshiftEntry const* formEntry = sSpellShapeshiftStore.LookupEntry(form);
18478  if (formEntry && formEntry->modelID_A)
18479  {
18480  // Take the alliance modelid as default
18481  if (GetTypeId() != TYPEID_PLAYER)
18482  return formEntry->modelID_A;
18483  else
18484  {
18486  modelid = formEntry->modelID_A;
18487  else
18488  modelid = formEntry->modelID_H;
18489 
18490  // If the player is horde but there are no values for the horde modelid - take the alliance modelid
18491  if (!modelid && Player::TeamIdForRace(getRace()) == TEAM_HORDE)
18492  modelid = formEntry->modelID_A;
18493  }
18494  }
18495 
18496  return modelid;
18497 }
18498 
18500 {
18501  switch (getRace())
18502  {
18503  case RACE_ORC:
18504  {
18505  switch (totemType)
18506  {
18507  case SUMMON_TYPE_TOTEM_FIRE: // fire
18508  return 30758;
18509  case SUMMON_TYPE_TOTEM_EARTH: // earth
18510  return 30757;
18511  case SUMMON_TYPE_TOTEM_WATER: // water
18512  return 30759;
18513  case SUMMON_TYPE_TOTEM_AIR: // air
18514  return 30756;
18515  }
18516  break;
18517  }
18518  case RACE_DWARF:
18519  {
18520  switch (totemType)
18521  {
18522  case SUMMON_TYPE_TOTEM_FIRE: // fire
18523  return 30754;
18524  case SUMMON_TYPE_TOTEM_EARTH: // earth
18525  return 30753;
18526  case SUMMON_TYPE_TOTEM_WATER: // water
18527  return 30755;
18528  case SUMMON_TYPE_TOTEM_AIR: // air
18529  return 30736;
18530  }
18531  break;
18532  }
18533  case RACE_TROLL:
18534  {
18535  switch (totemType)
18536  {
18537  case SUMMON_TYPE_TOTEM_FIRE: // fire
18538  return 30762;
18539  case SUMMON_TYPE_TOTEM_EARTH: // earth
18540  return 30761;
18541  case SUMMON_TYPE_TOTEM_WATER: // water
18542  return 30763;
18543  case SUMMON_TYPE_TOTEM_AIR: // air
18544  return 30760;
18545  }
18546  break;
18547  }
18548  case RACE_TAUREN:
18549  {
18550  switch (totemType)
18551  {
18552  case SUMMON_TYPE_TOTEM_FIRE: // fire
18553  return 4589;
18554  case SUMMON_TYPE_TOTEM_EARTH: // earth
18555  return 4588;
18556  case SUMMON_TYPE_TOTEM_WATER: // water
18557  return 4587;
18558  case SUMMON_TYPE_TOTEM_AIR: // air
18559  return 4590;
18560  }
18561  break;
18562  }
18563  case RACE_DRAENEI:
18564  {
18565  switch (totemType)
18566  {
18567  case SUMMON_TYPE_TOTEM_FIRE: // fire
18568  return 19074;
18569  case SUMMON_TYPE_TOTEM_EARTH: // earth
18570  return 19073;
18571  case SUMMON_TYPE_TOTEM_WATER: // water
18572  return 19075;
18573  case SUMMON_TYPE_TOTEM_AIR: // air
18574  return 19071;
18575  }
18576  break;
18577  }
18578  default: // One standard for other races.
18579  {
18580  switch (totemType)
18581  {
18582  case SUMMON_TYPE_TOTEM_FIRE: // fire
18583  return 4589;
18584  case SUMMON_TYPE_TOTEM_EARTH: // earth
18585  return 4588;
18586  case SUMMON_TYPE_TOTEM_WATER: // water
18587  return 4587;
18588  case SUMMON_TYPE_TOTEM_AIR: // air
18589  return 4590;
18590  }
18591  break;
18592  }
18593  }
18594  return 0;
18595 }
18596 
18598 {
18600 }
18601 
18602 void Unit::JumpTo(float speedXY, float speedZ, bool forward)
18603 {
18604  float angle = forward ? 0 : M_PI;
18605  if (GetTypeId() == TYPEID_UNIT)
18606  GetMotionMaster()->MoveJumpTo(angle, speedXY, speedZ);
18607  else
18608  {
18609  float vcos = cos(angle + GetOrientation());
18610  float vsin = sin(angle + GetOrientation());
18611 
18612  WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8 + 4 + 4 + 4 + 4 + 4));
18613  data << GetPackGUID();
18614  data << uint32(0); // Sequence
18615  data << float(vcos); // x direction
18616  data << float(vsin); // y direction
18617  data << float(speedXY); // Horizontal speed
18618  data << float(-speedZ); // Z Movement speed (vertical)
18619 
18621  }
18622 }
18623 
18624 void Unit::JumpTo(WorldObject* obj, float speedZ)
18625 {
18626  float x, y, z;
18627  obj->GetContactPoint(this, x, y, z);
18628  float speedXY = GetExactDist2d(x, y) * 10.0f / speedZ;
18629  GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ);
18630 }
18631 
18632 bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
18633 {
18634  bool result = false;
18635  uint32 spellClickEntry = GetVehicleKit() ? GetVehicleKit()->GetCreatureEntry() : GetEntry();
18636  SpellClickInfoMapBounds clickPair = sObjectMgr->GetSpellClickInfoMapBounds(spellClickEntry);
18637  for (SpellClickInfoContainer::const_iterator itr = clickPair.first; itr != clickPair.second; ++itr)
18638  {
18640  if (!itr->second.IsFitToRequirements(clicker, this))
18641  continue;
18642 
18644  ConditionList conds = sConditionMgr->GetConditionsForSpellClickEvent(spellClickEntry, itr->second.spellId);
18645  ConditionSourceInfo info = ConditionSourceInfo(clicker, this);
18646  if (!sConditionMgr->IsObjectMeetToConditions(info, conds))
18647  continue;
18648 
18649  Unit* caster = (itr->second.castFlags & NPC_CLICK_CAST_CASTER_CLICKER) ? clicker : this;
18650  Unit* target = (itr->second.castFlags & NPC_CLICK_CAST_TARGET_CLICKER) ? clicker : this;
18651  ObjectGuid origCasterGUID = (itr->second.castFlags & NPC_CLICK_CAST_ORIG_CASTER_OWNER) ? GetOwnerGUID() : clicker->GetGUID();
18652 
18653  SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->second.spellId);
18654 
18655  // xinef: dont allow players to enter vehicles on arena
18656  if (spellEntry->HasAura(SPELL_AURA_CONTROL_VEHICLE) && caster->GetTypeId() == TYPEID_PLAYER && caster->FindMap() && caster->FindMap()->IsBattleArena())
18657  continue;
18658 
18659  if (seatId > -1)
18660  {
18661  uint8 i = 0;
18662  bool valid = false;
18663  while (i < MAX_SPELL_EFFECTS)
18664  {
18665  if (spellEntry->Effects[i].ApplyAuraName == SPELL_AURA_CONTROL_VEHICLE)
18666  {
18667  valid = true;
18668  break;
18669  }
18670  ++i;
18671  }
18672 
18673  if (!valid)
18674  {
18675  LOG_ERROR("sql.sql", "Spell %u specified in npc_spellclick_spells is not a valid vehicle enter aura!", itr->second.spellId);
18676  continue;
18677  }
18678 
18679  if (IsInMap(caster))
18680  caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0 + i), seatId + 1, target, GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE, nullptr, nullptr, origCasterGUID);
18681  else // This can happen during Player::_LoadAuras
18682  {
18683  int32 bp0[MAX_SPELL_EFFECTS];
18684  for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
18685  bp0[j] = spellEntry->Effects[j].BasePoints;
18686 
18687  bp0[i] = seatId;
18688  Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, bp0, nullptr, origCasterGUID);
18689  }
18690  }
18691  else
18692  {
18693  if (IsInMap(caster))
18694  caster->CastSpell(target, spellEntry, GetVehicleKit() ? TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE : TRIGGERED_NONE, nullptr, nullptr, origCasterGUID);
18695  else
18696  Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, nullptr, nullptr, origCasterGUID);
18697  }
18698 
18699  result = true;
18700  }
18701 
18702  Creature* creature = ToCreature();
18703  if (creature && creature->IsAIEnabled)
18704  creature->AI()->OnSpellClick(clicker, result);
18705 
18706  return result;
18707 }
18708 
18709 void Unit::EnterVehicle(Unit* base, int8 seatId)
18710 {
18712 
18713  if (Player* player = ToPlayer())
18714  {
18715  sScriptMgr->AnticheatSetUnderACKmount(player);
18716  sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
18717  }
18718 }
18719 
18721 {
18722  CastCustomSpell(67830, SPELLVALUE_BASE_POINT0, seatId + 1, base, true);
18723 }
18724 
18725 void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp)
18726 {
18727  // Must be called only from aura handler
18728  if (!IsAlive() || GetVehicleKit() == vehicle || vehicle->GetBase()->IsOnVehicle(this))
18729  return;
18730 
18731  if (m_vehicle)
18732  {
18733  if (m_vehicle == vehicle)
18734  {
18735  if (seatId >= 0 && seatId != GetTransSeat())
18736  {
18737  LOG_DEBUG("vehicles", "EnterVehicle: %u leave vehicle %u seat %d and enter %d.", GetEntry(), m_vehicle->GetBase()->GetEntry(), GetTransSeat(), seatId);
18738  ChangeSeat(seatId);
18739  }
18740 
18741  return;
18742  }
18743  else
18744  {
18745  LOG_DEBUG("vehicles", "EnterVehicle: %u exit %u and enter %u.", GetEntry(), m_vehicle->GetBase()->GetEntry(), vehicle->GetBase()->GetEntry());
18746  ExitVehicle();
18747  }
18748  }
18749 
18750  if (!aurApp || aurApp->GetRemoveMode())
18751  return;
18752 
18753  if (Player* player = ToPlayer())
18754  {
18755  if (vehicle->GetBase()->GetTypeId() == TYPEID_PLAYER && player->IsInCombat())
18756  return;
18757 
18758  sScriptMgr->AnticheatSetUnderACKmount(player);
18759  sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
18760 
18761  InterruptNonMeleeSpells(false);
18762  player->StopCastingCharm();
18763  player->StopCastingBindSight();
18764  Dismount();
18766 
18767  // drop flag at invisible in bg
18768  if (Battleground* bg = player->GetBattleground())
18769  bg->EventPlayerDroppedFlag(player);
18770 
18772  player->GetSession()->SendPacket(&data);
18773  }
18774 
18775  ASSERT(!m_vehicle);
18776  m_vehicle = vehicle;
18777 
18778  if (!m_vehicle->AddPassenger(this, seatId))
18779  {
18780  m_vehicle = nullptr;
18781  return;
18782  }
18783 
18784  // Xinef: remove movement auras when entering vehicle (food buffs etc)
18786 }
18787 
18788 void Unit::ChangeSeat(int8 seatId, bool next)
18789 {
18790  if (!m_vehicle)
18791  return;
18792 
18793  if (seatId < 0)
18794  {
18796  if (seatId < 0)
18797  return;
18798  }
18799  else if (seatId == GetTransSeat() || !m_vehicle->HasEmptySeat(seatId))
18800  return;
18801 
18802  m_vehicle->RemovePassenger(this);
18803  if (!m_vehicle->AddPassenger(this, seatId))
18804  ABORT();
18805 }
18806 
18807 void Unit::ExitVehicle(Position const* /*exitPosition*/)
18808 {
18810  if (!m_vehicle)
18811  return;
18812 
18817  /*_ExitVehicle(exitPosition);*/
18824 
18825  if (Player* player = ToPlayer())
18826  {
18827  sScriptMgr->AnticheatSetUnderACKmount(player);
18828  sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
18829  }
18830 }
18831 
18832 bool VehicleDespawnEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
18833 {
18834  Position pos = _self;
18838  return true;
18839 }
18840 
18841 void Unit::_ExitVehicle(Position const* exitPosition)
18842 {
18843  if (!m_vehicle)
18844  return;
18845 
18846  m_vehicle->RemovePassenger(this);
18847 
18848  Player* player = ToPlayer();
18849 
18850  // If player is on mouted duel and exits the mount should immediatly lose the duel
18851  if (player && player->duel && player->duel->isMounted)
18852  player->DuelComplete(DUEL_FLED);
18853 
18854  // This should be done before dismiss, because there may be some aura removal
18855  Vehicle* vehicle = m_vehicle;
18856  Unit* vehicleBase = m_vehicle->GetBase();
18857  m_vehicle = nullptr;
18858 
18859  SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
18860 
18861  Position pos;
18862  if (!exitPosition) // Exit position not specified
18863  pos = vehicleBase->GetPosition(); // This should use passenger's current position, leaving it as it is now
18864  // because we calculate positions incorrect (sometimes under map)
18865  else
18866  pos = *exitPosition;
18867 
18868  // HACK
18869  if (vehicle->GetVehicleInfo()->m_ID == 380) // Kologarn right arm
18870  pos.Relocate(1776.0f, -24.0f, 448.75f, 0.0f);
18871  else if (vehicle->GetVehicleInfo()->m_ID == 91) // Helsman's Ship
18872  pos.Relocate(2802.18f, 7054.91f, -0.6f, 4.67f);
18873  else if (vehicle->GetVehicleInfo()->m_ID == 349) // AT Mounts, dismount to the right
18874  {
18875  float x = pos.GetPositionX() + 2.0f * cos(pos.GetOrientation() - M_PI / 2.0f);
18876  float y = pos.GetPositionY() + 2.0f * sin(pos.GetOrientation() - M_PI / 2.0f);
18877  float z = GetMapHeight(x, y, pos.GetPositionZ());
18878  if (z > INVALID_HEIGHT)
18879  pos.Relocate(x, y, z);
18880  }
18881 
18883 
18884  if (player)
18885  {
18886  player->SetFallInformation(time(nullptr), GetPositionZ());
18887 
18888  sScriptMgr->AnticheatSetUnderACKmount(player);
18889  sScriptMgr->AnticheatSetSkipOnePacketForASH(player, true);
18890  }
18892  {
18894  data << GetPackGUID();
18895  SendMessageToSet(&data, false);
18896  }
18897 
18898  // xinef: hack for flameleviathan seat vehicle
18899  if (vehicle->GetVehicleInfo()->m_ID != 341)
18900  {
18901  Movement::MoveSplineInit init(this);
18902  init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
18903  init.SetFacing(GetOrientation());
18904  init.SetTransportExit();
18905  init.Launch();
18906  }
18907  else
18908  {
18909  float o = pos.GetAngle(this);
18910  Movement::MoveSplineInit init(this);
18911  init.MoveTo(pos.GetPositionX() + 8 * cos(o), pos.GetPositionY() + 8 * sin(o), pos.GetPositionZ() + 16.0f);
18912  init.SetFacing(GetOrientation());
18913  init.SetTransportExit();
18914  init.Launch();
18915  DisableSpline();
18916  KnockbackFrom(pos.GetPositionX(), pos.GetPositionY(), 10.0f, 20.0f);
18917  CastSpell(this, VEHICLE_SPELL_PARACHUTE, true);
18918  }
18919 
18920  // xinef: move fall, should we support all creatures that exited vehicle in air? Currently Quest Drag and Drop only, Air Assault quest
18921  if (GetTypeId() == TYPEID_UNIT && !CanFly() &&
18922  (vehicle->GetVehicleInfo()->m_ID == 113 || vehicle->GetVehicleInfo()->m_ID == 8 || vehicle->GetVehicleInfo()->m_ID == 290 || vehicle->GetVehicleInfo()->m_ID == 298))
18924  //GetMotionMaster()->MoveFall(); // Enable this once passenger positions are calculater properly (see above)
18925 
18926  if ((!player || !(player->GetDelayedOperations() & DELAYED_VEHICLE_TELEPORT)) && vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
18927  if (((Minion*)vehicleBase)->GetOwner() == this)
18928  {
18929  if (vehicle->GetVehicleInfo()->m_ID != 349)
18930  vehicle->Dismiss();
18931  else if (vehicleBase->GetTypeId() == TYPEID_UNIT)
18932  {
18933  vehicle->Uninstall();
18934  vehicleBase->m_Events.AddEvent(new VehicleDespawnEvent(*vehicleBase, 2000), vehicleBase->m_Events.CalculateTime(2000));
18935  }
18936 
18937  // xinef: ugly hack, no appripriate hook later to cast spell
18938  if (player)
18939  {
18940  if (vehicleBase->GetEntry() == NPC_EIDOLON_WATCHER)
18941  player->CastSpell(player, VEHICLE_SPELL_SHADE_CONTROL_END, true);
18942  else if (vehicleBase->GetEntry() == NPC_LITHE_STALKER)
18943  player->CastSpell(player, VEHICLE_SPELL_GEIST_CONTROL_END, true);
18944  }
18945  }
18946 
18948  {
18949  // Vehicle just died, we die too
18950  if (vehicleBase->getDeathState() == JUST_DIED)
18952  // If for other reason we as minion are exiting the vehicle (ejected, master dismounted) - unsummon
18953  else
18954  {
18955  SetVisible(false);
18956  ToTempSummon()->UnSummon(2000); // Approximation
18957  }
18958  }
18959 
18960  if (player)
18962 }
18963 
18965 {
18966  *data << uint32(GetUnitMovementFlags()); // movement flags
18967  *data << uint16(GetExtraUnitMovementFlags()); // 2.3.0
18968  *data << uint32(World::GetGameTimeMS()); // time / counter
18969  *data << GetPositionX();
18970  *data << GetPositionY();
18971  *data << GetPositionZ();
18972  *data << GetOrientation();
18973 
18974  // 0x00000200
18976  {
18977  if (m_vehicle)
18978  *data << m_vehicle->GetBase()->GetPackGUID();
18979  else if (GetTransport())
18980  *data << GetTransport()->GetPackGUID();
18981  else
18982  *data << (uint8)0;
18983 
18984  *data << float (GetTransOffsetX());
18985  *data << float (GetTransOffsetY());
18986  *data << float (GetTransOffsetZ());
18987  *data << float (GetTransOffsetO());
18988  *data << uint32(GetTransTime());
18989  *data << uint8 (GetTransSeat());
18990 
18993  }
18994 
18995  // 0x02200000
18998  *data << (float)m_movementInfo.pitch;
18999 
19001 
19002  // 0x00001000
19004  {
19005  *data << (float)m_movementInfo.jump.zspeed;
19006  *data << (float)m_movementInfo.jump.sinAngle;
19007  *data << (float)m_movementInfo.jump.cosAngle;
19008  *data << (float)m_movementInfo.jump.xyspeed;
19009  }
19010 
19011  // 0x04000000
19013  *data << (float)m_movementInfo.splineElevation;
19014 }
19015 
19016 bool Unit::IsFalling() const
19017 {
19019 }
19020 
19028 bool Unit::CanSwim() const
19029 {
19030  // Mirror client behavior, if this method returns false then client will not use swimming animation and for players will apply gravity as if there was no water
19032  return false;
19033  if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_POSSESSED)) // is player
19034  return true;
19035  if (HasFlag(UNIT_FIELD_FLAGS_2, 0x1000000))
19036  return false;
19038  return true;
19040 }
19041 
19042 void Unit::NearTeleportTo(float x, float y, float z, float orientation, bool casting /*= false*/, bool vehicleTeleport /*= false*/, bool withPet /*= false*/, bool removeTransport /*= false*/)
19043 {
19044  DisableSpline();
19045  if (GetTypeId() == TYPEID_PLAYER)
19046  ToPlayer()->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | (removeTransport ? 0 : TELE_TO_NOT_LEAVE_TRANSPORT) | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0) | (vehicleTeleport ? TELE_TO_NOT_LEAVE_VEHICLE : 0) | (withPet ? TELE_TO_WITH_PET : 0));
19047  else
19048  {
19049  Position pos = {x, y, z, orientation};
19051  UpdatePosition(x, y, z, orientation, true);
19054  }
19055 }
19056 
19058 {
19060  data << uint8(result);
19062 }
19063 
19065 {
19067  if (GetTypeId() == TYPEID_UNIT)
19068  Relocate(&pos);
19069 
19070  WorldPacket data2(MSG_MOVE_TELEPORT, 38);
19071  data2 << GetPackGUID();
19072  BuildMovementPacket(&data2);
19073  if (GetTypeId() == TYPEID_UNIT)
19074  Relocate(&oldPos);
19075  if (GetTypeId() == TYPEID_PLAYER)
19076  Relocate(&pos);
19077  SendMessageToSet(&data2, false);
19078 }
19079 
19080 bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool teleport)
19081 {
19082  if (!Acore::IsValidMapCoord(x, y, z, orientation))
19083  return false;
19084 
19085  float old_orientation = GetOrientation();
19086  float current_z = GetPositionZ();
19087  bool turn = (old_orientation != orientation);
19088  bool relocated = (teleport || GetPositionX() != x || GetPositionY() != y || current_z != z);
19089 
19090  if (!GetVehicle())
19091  {
19092  uint32 mask = 0;
19093  if (turn) mask |= AURA_INTERRUPT_FLAG_TURNING;
19094  if (relocated) mask |= AURA_INTERRUPT_FLAG_MOVE;
19095  if (mask)
19097  }
19098 
19099  if (relocated)
19100  {
19101  if (GetTypeId() == TYPEID_PLAYER)
19102  GetMap()->PlayerRelocation(ToPlayer(), x, y, z, orientation);
19103  else
19104  GetMap()->CreatureRelocation(ToCreature(), x, y, z, orientation);
19105  }
19106  else if (turn)
19107  {
19108  UpdateOrientation(orientation);
19109 
19110  if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetFarSightDistance())
19111  UpdateObjectVisibility(false);
19112  }
19113 
19114  return (relocated || turn);
19115 }
19116 
19118 void Unit::UpdateOrientation(float orientation)
19119 {
19120  SetOrientation(orientation);
19121  if (IsVehicle())
19123 }
19124 
19126 void Unit::UpdateHeight(float newZ)
19127 {
19128  Relocate(GetPositionX(), GetPositionY(), newZ);
19129  if (IsVehicle())
19131 }
19132 
19134 {
19135  if (!getThreatMgr().isThreatListEmpty())
19136  {
19137  uint32 count = getThreatMgr().getThreatList().size();
19138 
19139  //LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_UPDATE Message");
19141  data << GetPackGUID();
19142  data << uint32(count);
19144  for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
19145  {
19146  data << (*itr)->getUnitGuid().WriteAsPacked();
19147  data << uint32((*itr)->getThreat() * 100);
19148  }
19149  SendMessageToSet(&data, false);
19150  }
19151 }
19152 
19154 {
19155  if (!getThreatMgr().isThreatListEmpty())
19156  {
19157  uint32 count = getThreatMgr().getThreatList().size();
19158 
19159  LOG_DEBUG("entities.unit", "WORLD: Send SMSG_HIGHEST_THREAT_UPDATE Message");
19161  data << GetPackGUID();
19162  data << pHostileReference->getUnitGuid().WriteAsPacked();
19163  data << uint32(count);
19165  for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr)
19166  {
19167  data << (*itr)->getUnitGuid().WriteAsPacked();
19168  data << uint32((*itr)->getThreat() * 100);
19169  }
19170  SendMessageToSet(&data, false);
19171  }
19172 }
19173 
19175 {
19176  LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_CLEAR Message");
19178  data << GetPackGUID();
19179  SendMessageToSet(&data, false);
19180 }
19181 
19183 {
19184  LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_REMOVE Message");
19186  data << GetPackGUID();
19187  data << pHostileReference->getUnitGuid().WriteAsPacked();
19188  SendMessageToSet(&data, false);
19189 }
19190 
19191 void Unit::RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker)
19192 {
19193  float addRage;
19194 
19195  float rageconversion = ((0.0091107836f * getLevel() * getLevel()) + 3.225598133f * getLevel()) + 4.2652911f;
19196 
19197  // Unknown if correct, but lineary adjust rage conversion above level 70
19198  if (getLevel() > 70)
19199  rageconversion += 13.27f * (getLevel() - 70);
19200 
19201  if (attacker)
19202  {
19203  addRage = (damage / rageconversion * 7.5f + weaponSpeedHitFactor) / 2;
19204 
19205  // talent who gave more rage on attack
19207  }
19208  else
19209  {
19210  addRage = damage / rageconversion * 2.5f;
19211 
19212  // Berserker Rage effect
19213  if (HasAura(18499))
19214  addRage *= 3.0f;
19215  }
19216 
19217  addRage *= sWorld->getRate(RATE_POWER_RAGE_INCOME);
19218 
19219  ModifyPower(POWER_RAGE, uint32(addRage * 10));
19220 }
19221 
19223 {
19224  if (Unit* victim = GetVictim())
19225  {
19226  if (victim->GetFactionTemplateEntry()->faction == faction_id)
19227  {
19228  AttackStop();
19229  if (IsNonMeleeSpellCast(false))
19230  InterruptNonMeleeSpells(false);
19231 
19232  // melee and ranged forced attack cancel
19233  if (GetTypeId() == TYPEID_PLAYER)
19235  }
19236  }
19237 
19238  AttackerSet const& attackers = getAttackers();
19239  for (AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
19240  {
19241  if ((*itr)->GetFactionTemplateEntry()->faction == faction_id)
19242  {
19243  (*itr)->AttackStop();
19244  itr = attackers.begin();
19245  }
19246  else
19247  ++itr;
19248  }
19249 
19251 
19252  for (ControlSet::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
19253  (*itr)->StopAttackFaction(faction_id);
19254 }
19255 
19257 {
19258  LOG_ERROR("entities.unit", "Unit::OutDebugInfo");
19259  LOG_INFO("entities.unit", "GUID %s, name %s", GetGUID().ToString().c_str(), GetName().c_str());
19260  LOG_INFO("entities.unit", "OwnerGUID %s, MinionGUID %s, CharmerGUID %s, CharmedGUID %s",
19261  GetOwnerGUID().ToString().c_str(), GetMinionGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), GetCharmGUID().ToString().c_str());
19262  LOG_INFO("entities.unit", "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask);
19263  if (IsInWorld())
19264  LOG_INFO("entities.unit", "Mapid %u", GetMapId());
19265 
19266  LOG_INFO("entities.unit", "Summon Slot: ");
19267  for (uint32 i = 0; i < MAX_SUMMON_SLOT; ++i)
19268  LOG_INFO("entities.unit", "%s, ", m_SummonSlot[i].ToString().c_str());
19269  LOG_INFO("server.loading", " ");
19270 
19271  LOG_INFO("entities.unit", "Controlled List: ");
19272  for (ControlSet::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
19273  LOG_INFO("entities.unit", "%s, ", (*itr)->GetGUID().ToString().c_str());
19274  LOG_INFO("server.loading", " ");
19275 
19276  LOG_INFO("entities.unit", "Aura List: ");
19277  for (AuraApplicationMap::const_iterator itr = m_appliedAuras.begin(); itr != m_appliedAuras.end(); ++itr)
19278  LOG_INFO("entities.unit", "%u, ", itr->first);
19279  LOG_INFO("server.loading", " ");
19280 
19281  if (IsVehicle())
19282  {
19283  LOG_INFO("entities.unit", "Passenger List: ");
19284  for (SeatMap::iterator itr = GetVehicleKit()->Seats.begin(); itr != GetVehicleKit()->Seats.end(); ++itr)
19285  if (Unit* passenger = ObjectAccessor::GetUnit(*GetVehicleBase(), itr->second.Passenger.Guid))
19286  LOG_INFO("entities.unit", "%s, ", passenger->GetGUID().ToString().c_str());
19287  LOG_INFO("server.loading", " ");
19288  }
19289 
19290  if (GetVehicle())
19291  LOG_INFO("entities.unit", "On vehicle %u.", GetVehicleBase()->GetEntry());
19292 }
19293 
19295 {
19296 public:
19297  AuraMunchingQueue(Unit& owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId) : _owner(owner), _targetGUID(targetGUID), _basePoints(basePoints), _spellId(spellId) { }
19298 
19299  bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
19300  {
19301  if (_owner.IsInWorld() && _owner.FindMap())
19304 
19305  return true;
19306  }
19307 
19308 private:
19313 };
19314 
19315 void Unit::CastDelayedSpellWithPeriodicAmount(Unit* caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex)
19316 {
19317  for (AuraEffectList::iterator i = m_modAuras[auraType].begin(); i != m_modAuras[auraType].end(); ++i)
19318  {
19319  AuraEffect* aurEff = *i;
19320  if (aurEff->GetCasterGUID() != caster->GetGUID() || aurEff->GetId() != spellId || aurEff->GetEffIndex() != effectIndex || !aurEff->GetTotalTicks())
19321  continue;
19322 
19323  addAmount += ((aurEff->GetOldAmount() * std::max<int32>(aurEff->GetTotalTicks() - int32(aurEff->GetTickNumber()), 0)) / aurEff->GetTotalTicks());
19324  break;
19325  }
19326 
19327  // xinef: delay only for casting on different unit
19328  if (this == caster)
19329  caster->CastCustomSpell(spellId, SPELLVALUE_BASE_POINT0, addAmount, this, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_NO_PERIODIC_RESET), nullptr, nullptr, caster->GetGUID());
19330  else
19331  caster->m_Events.AddEvent(new AuraMunchingQueue(*caster, GetGUID(), addAmount, spellId), caster->m_Events.CalculateQueueTime(400));
19332 }
19333 
19335 {
19337  data << GetPackGUID();
19338  SendMessageToSet(&data, false);
19339 }
19340 
19342 {
19343  int32 resist = -1;
19344  for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
19345  if (mask & (1 << i) && (resist < 0 || resist > int32(GetResistance(SpellSchools(i)))))
19346  resist = int32(GetResistance(SpellSchools(i)));
19347 
19348  // resist value will never be negative here
19349  return uint32(resist);
19350 }
19351 
19353 {
19354  _isCommandAttack = val;
19355 }
19356 
19358 {
19359  return _isCommandAttack;
19360 }
19361 
19363 {
19364  _isCommandFollow = val;
19365 }
19366 
19368 {
19369  return _isCommandFollow;
19370 }
19371 
19372 void CharmInfo::SaveStayPosition(bool atCurrentPos)
19373 {
19375  G3D::Vector3 stayPos = G3D::Vector3();
19376 
19377  if (atCurrentPos)
19378  {
19379  float z = INVALID_HEIGHT;
19382  }
19383  else
19384  stayPos = _unit->movespline->FinalDestination();
19385 
19387  if (TransportBase* transport = _unit->GetDirectTransport())
19388  transport->CalculatePassengerPosition(stayPos.x, stayPos.y, stayPos.z);
19389 
19390  _stayX = stayPos.x;
19391  _stayY = stayPos.y;
19392  _stayZ = stayPos.z;
19393 }
19394 
19395 void CharmInfo::GetStayPosition(float& x, float& y, float& z)
19396 {
19397  x = _stayX;
19398  y = _stayY;
19399  z = _stayZ;
19400 }
19401 
19403 {
19404  _stayX = 0.0f;
19405  _stayY = 0.0f;
19406  _stayZ = 0.0f;
19407 }
19408 
19410 {
19411  return _stayX && _stayY && _stayZ;
19412 }
19413 
19415 {
19416  _isAtStay = val;
19417 }
19418 
19420 {
19421  return _isAtStay;
19422 }
19423 
19425 {
19426  _isFollowing = val;
19427 }
19428 
19430 {
19431  return _isFollowing;
19432 }
19433 
19435 {
19436  _isReturning = val;
19437 }
19438 
19440 {
19441  return _isReturning;
19442 }
19443 
19444 void Unit::PetSpellFail(const SpellInfo* spellInfo, Unit* target, uint32 result)
19445 {
19446  CharmInfo* charmInfo = GetCharmInfo();
19447  if (!charmInfo || GetTypeId() != TYPEID_UNIT)
19448  return;
19449 
19451  {
19453  if (Unit* owner = GetOwner())
19454  {
19455  if (spellInfo->IsPositive() && IsFriendlyTo(target))
19456  {
19457  AttackStop();
19458  charmInfo->SetIsAtStay(false);
19459  charmInfo->SetIsCommandAttack(!ToCreature()->HasReactState(REACT_PASSIVE));
19460  charmInfo->SetIsReturning(false);
19461  charmInfo->SetIsFollowing(false);
19462 
19464  }
19465  else if (owner->IsValidAttackTarget(target))
19466  {
19467  AttackStop();
19468  charmInfo->SetIsAtStay(false);
19469  charmInfo->SetIsCommandAttack(!ToCreature()->HasReactState(REACT_PASSIVE));
19470  charmInfo->SetIsReturning(false);
19471  charmInfo->SetIsFollowing(false);
19472 
19473  if (!ToCreature()->HasReactState(REACT_PASSIVE))
19474  ToCreature()->AI()->AttackStart(target);
19475  else
19476  GetMotionMaster()->MoveChase(target);
19477  }
19478  }
19479 
19480  // can be extended in future
19482  {
19483  charmInfo->SetForcedSpell(spellInfo->IsPositive() ? -int32(spellInfo->Id) : spellInfo->Id);
19484  charmInfo->SetForcedTargetGUID(target->GetGUID());
19485  }
19486  else
19487  {
19488  charmInfo->SetForcedSpell(0);
19490  }
19491  }
19492 }
19493 
19494 int32 Unit::CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, Unit* caster) const
19495 {
19496  damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, schoolMask));
19497  if (caster && caster->GetTypeId() == TYPEID_UNIT)
19499 
19500  return damage;
19501 }
19502 
19504 {
19505  if (m_owner->IsInWorld())
19509 
19510  return true;
19511 }
19512 
19514 {
19516  if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
19517  return;
19518 
19519  if (this->HasSharedVision())
19520  for (SharedVisionList::const_iterator itr = this->GetSharedVisionList().begin(); itr != this->GetSharedVisionList().end(); ++itr)
19521  if (Player* player = (*itr))
19522  {
19523  if (player->IsOnVehicle(this) || !player->IsInWorld() || player->IsDuringRemoveFromWorld()) // players on vehicles have their own event executed (due to passenger relocation)
19524  continue;
19525  WorldObject* viewPoint = player;
19526  if (player->m_seer && player->m_seer->IsInWorld())
19527  viewPoint = player->m_seer;
19528  if (!viewPoint->IsPositionValid() || !player->IsPositionValid())
19529  continue;
19530 
19531  if (Unit* active = viewPoint->ToUnit())
19532  {
19533  //if (active->IsVehicle()) // always check original unit here, last notify position is not relocated
19534  // active = player;
19535 
19536  float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
19537  float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
19538  float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
19539  float distsq = dx * dx + dy * dy + dz * dz;
19540  float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
19541  if (distsq < mindistsq)
19542  continue;
19543 
19544  // this will be relocated below sharedvision!
19545  //active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
19546  }
19547 
19548  Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
19549  Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
19550  relocateNoLarge.SendToSelf();
19551  Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
19552  Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
19553  relocateLarge.SendToSelf();
19554  }
19555 
19556  if (Player* player = this->ToPlayer())
19557  {
19558  WorldObject* viewPoint = player;
19559  if (player->m_seer && player->m_seer->IsInWorld())
19560  viewPoint = player->m_seer;
19561 
19562  if (viewPoint->GetMapId() != player->GetMapId() || !viewPoint->IsPositionValid() || !player->IsPositionValid())
19563  return;
19564 
19565  if (Unit* active = viewPoint->ToUnit())
19566  {
19567  if (active->IsVehicle())
19568  active = player;
19569 
19570  if (!player->GetFarSightDistance())
19571  {
19572  float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
19573  float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
19574  float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
19575  float distsq = dx * dx + dy * dy + dz * dz;
19576 
19577  float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
19578  if (distsq < mindistsq)
19579  return;
19580 
19581  active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
19582  }
19583  }
19584 
19585  Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
19586  Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
19587  relocateNoLarge.SendToSelf();
19588 
19589  if (!player->GetFarSightDistance())
19590  {
19591  Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
19592  Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
19593  relocateLarge.SendToSelf();
19594  }
19595 
19597  }
19598  else if (Creature* unit = this->ToCreature())
19599  {
19600  if (!unit->IsPositionValid())
19601  return;
19602 
19603  float dx = unit->m_last_notify_position.GetPositionX() - unit->GetPositionX();
19604  float dy = unit->m_last_notify_position.GetPositionY() - unit->GetPositionY();
19605  float dz = unit->m_last_notify_position.GetPositionZ() - unit->GetPositionZ();
19606  float distsq = dx * dx + dy * dy + dz * dz;
19607  float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(unit->FindMap()->GetEntry()->map_type);
19608  if (distsq < mindistsq)
19609  return;
19610 
19611  unit->m_last_notify_position.Relocate(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
19612 
19613  Acore::CreatureRelocationNotifier relocate(*unit);
19614  Cell::VisitAllObjects(unit, relocate, unit->GetVisibilityRange() + VISIBILITY_COMPENSATION);
19615 
19617  }
19618 }
19619 
19621 {
19623  if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
19624  return;
19625 
19626  Acore::AIRelocationNotifier notifier(*this);
19627  float radius = 60.0f;
19628  Cell::VisitAllObjects(this, notifier, radius);
19629 }
19630 
19631 void Unit::SetInFront(WorldObject const* target)
19632 {
19634  SetOrientation(GetAngle(target));
19635 }
19636 
19637 void Unit::SetFacingTo(float ori)
19638 {
19639  Movement::MoveSplineInit init(this);
19640  init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
19642  init.DisableTransportPathTransformations(); // It makes no sense to target global orientation
19643  init.SetFacing(ori);
19644  init.Launch();
19645 }
19646 
19648 {
19649  // never face when already moving
19650  if (!IsStopped())
19651  return;
19652 
19654  Movement::MoveSplineInit init(this);
19656  init.SetFacing(GetAngle(object)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming
19657  init.Launch();
19658 }
19659 
19660 bool Unit::SetWalk(bool enable)
19661 {
19662  if (enable == IsWalking())
19663  return false;
19664 
19665  if (enable)
19667  else
19669 
19671  return true;
19672 }
19673 
19674 bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/)
19675 {
19676  if (disable == IsLevitating())
19677  return false;
19678 
19679  if (disable)
19680  {
19683  }
19684  else
19685  {
19687  }
19688 
19689  return true;
19690 }
19691 
19692 bool Unit::SetSwim(bool enable)
19693 {
19695  return false;
19696 
19697  if (enable)
19698  {
19701  }
19702  else
19703  {
19706  }
19707 
19708  return true;
19709 }
19710 
19711 bool Unit::SetCanFly(bool enable, bool /*packetOnly = false */)
19712 {
19714  return false;
19715 
19716  if (enable)
19717  {
19720  }
19721  else
19722  {
19724  }
19725 
19726  return true;
19727 }
19728 
19729 bool Unit::SetWaterWalking(bool enable, bool /*packetOnly = false*/)
19730 {
19732  return false;
19733 
19734  if (enable)
19736  else
19738 
19739  return true;
19740 }
19741 
19743 {
19744  if (!movespline->Initialized())
19745  return;
19747  data << GetPackGUID();
19748  sendTo->SendDirectMessage(&data);
19749 }
19750 
19751 bool Unit::SetFeatherFall(bool enable, bool /*packetOnly = false*/)
19752 {
19754  return false;
19755 
19756  if (enable)
19758  else
19760 
19761  return true;
19762 }
19763 
19765 {
19766  if (!movespline->Initialized())
19767  return;
19769  data << GetPackGUID();
19770  sendTo->SendDirectMessage(&data);
19771 }
19772 
19773 bool Unit::SetHover(bool enable, bool /*packetOnly = false*/)
19774 {
19775  if (enable == HasUnitMovementFlag(MOVEMENTFLAG_HOVER))
19776  return false;
19777 
19778  float hoverHeight = GetFloatValue(UNIT_FIELD_HOVERHEIGHT);
19779 
19780  if (enable)
19781  {
19783  if (hoverHeight && GetPositionZ() - GetFloorZ() < hoverHeight)
19784  UpdateHeight(GetPositionZ() + hoverHeight);
19785  }
19786  else
19787  {
19789  if (hoverHeight && (!isDying() || GetTypeId() != TYPEID_UNIT))
19790  {
19791  float newZ = std::max<float>(GetFloorZ(), GetPositionZ() - hoverHeight);
19793  UpdateHeight(newZ);
19794  }
19795  SendMovementFlagUpdate(); // pussywizard: needed for falling after death (instead of falling onto air at hover height)
19796  }
19797 
19798  return true;
19799 }
19800 
19802 {
19803  if (!movespline->Initialized())
19804  return;
19806  data << GetPackGUID();
19807  sendTo->SendDirectMessage(&data);
19808 }
19809 
19810 void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
19811 {
19812  if (!target)
19813  return;
19814 
19815  ByteBuffer fieldBuffer;
19816 
19817  UpdateMask updateMask;
19818  updateMask.SetCount(m_valuesCount);
19819 
19820  uint32* flags = UnitUpdateFieldFlags;
19821  uint32 visibleFlag = UF_FLAG_PUBLIC;
19822 
19823  if (target == this)
19824  visibleFlag |= UF_FLAG_PRIVATE;
19825 
19827  if (GetOwnerGUID() == target->GetGUID())
19828  visibleFlag |= UF_FLAG_OWNER;
19829 
19832  visibleFlag |= UF_FLAG_SPECIAL_INFO;
19833 
19834  if (plr && plr->IsInSameRaidWith(target))
19835  visibleFlag |= UF_FLAG_PARTY_MEMBER;
19836 
19837  Creature const* creature = ToCreature();
19838  for (uint16 index = 0; index < m_valuesCount; ++index)
19839  {
19840  if (_fieldNotifyFlags & flags[index] ||
19841  ((flags[index] & visibleFlag) & UF_FLAG_SPECIAL_INFO) ||
19842  ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)) ||
19844  {
19845  updateMask.SetBit(index);
19846 
19847  if (index == UNIT_NPC_FLAGS)
19848  {
19849  uint32 appendValue = m_uint32Values[UNIT_NPC_FLAGS];
19850 
19851  if (creature)
19852  {
19853  if (sWorld->getIntConfig(CONFIG_INSTANT_TAXI) == 2 && appendValue & UNIT_NPC_FLAG_FLIGHTMASTER)
19854  {
19855  appendValue |= UNIT_NPC_FLAG_GOSSIP; // flight masters need NPC gossip flag to show instant flight toggle option
19856  }
19857 
19858  if (!target->CanSeeSpellClickOn(creature))
19859  {
19860  appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
19861  }
19862 
19863  if (!creature->IsValidTrainerForPlayer(target, &appendValue))
19864  {
19865  appendValue &= ~UNIT_NPC_FLAG_TRAINER;
19866  }
19867  }
19868 
19869  fieldBuffer << uint32(appendValue);
19870  }
19871  else if (index == UNIT_FIELD_AURASTATE)
19872  {
19873  // Check per caster aura states to not enable using a spell in client if specified aura is not by target
19874  fieldBuffer << BuildAuraStateUpdateForTarget(target);
19875  }
19876  // FIXME: Some values at server stored in float format but must be sent to client in uint32 format
19878  {
19879  // convert from float to uint32 and send
19880  fieldBuffer << uint32(m_floatValues[index] < 0 ? 0 : m_floatValues[index]);
19881  }
19882  // there are some float values which may be negative or can't get negative due to other checks
19883  else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) ||
19887  {
19888  fieldBuffer << uint32(m_floatValues[index]);
19889  }
19890  // Gamemasters should be always able to select units - remove not selectable flag
19891  else if (index == UNIT_FIELD_FLAGS)
19892  {
19893  uint32 appendValue = m_uint32Values[UNIT_FIELD_FLAGS];
19894  if (target->IsGameMaster() && AccountMgr::IsGMAccount(target->GetSession()->GetSecurity()))
19895  appendValue &= ~UNIT_FLAG_NOT_SELECTABLE;
19896 
19897  fieldBuffer << uint32(appendValue);
19898  }
19899  // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
19900  else if (index == UNIT_FIELD_DISPLAYID)
19901  {
19903  if (creature)
19904  {
19905  CreatureTemplate const* cinfo = creature->GetCreatureTemplate();
19906 
19907  // this also applies for transform auras
19908  if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(getTransForm()))
19909  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
19910  if (transform->Effects[i].IsAura(SPELL_AURA_TRANSFORM))
19911  if (CreatureTemplate const* transformInfo = sObjectMgr->GetCreatureTemplate(transform->Effects[i].MiscValue))
19912  {
19913  cinfo = transformInfo;
19914  break;
19915  }
19916 
19918  {
19919  if (target->IsGameMaster() && AccountMgr::IsGMAccount(target->GetSession()->GetSecurity()))
19920  {
19921  if (cinfo->Modelid1)
19922  displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
19923  else
19924  displayId = 17519; // world visible trigger's model
19925  }
19926  else
19927  {
19928  if (cinfo->Modelid2)
19929  displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
19930  else
19931  displayId = 11686; // world invisible trigger's model
19932  }
19933  }
19934  }
19935 
19936  fieldBuffer << uint32(displayId);
19937  }
19938  // hide lootable animation for unallowed players
19939  else if (index == UNIT_DYNAMIC_FLAGS)
19940  {
19942 
19943  if (creature)
19944  {
19945  if (creature->hasLootRecipient())
19946  {
19947  dynamicFlags |= UNIT_DYNFLAG_TAPPED;
19948  if (creature->isTappedBy(target))
19949  dynamicFlags |= UNIT_DYNFLAG_TAPPED_BY_PLAYER;
19950  }
19951 
19952  if (!target->isAllowedToLoot(creature))
19953  dynamicFlags &= ~UNIT_DYNFLAG_LOOTABLE;
19954  }
19955 
19956  // unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
19957  if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT)
19959  dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT;
19960 
19961  fieldBuffer << dynamicFlags;
19962  }
19963  // FG: pretend that OTHER players in own group are friendly ("blue")
19965  {
19966  if (IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsInRaidWith(target))
19967  {
19969  FactionTemplateEntry const* ft2 = target->GetFactionTemplateEntry();
19970  if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
19971  {
19972  if (index == UNIT_FIELD_BYTES_2)
19973  // Allow targetting opposite faction in party when enabled in config
19974  fieldBuffer << (m_uint32Values[UNIT_FIELD_BYTES_2] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8)); // this flag is at uint8 offset 1 !!
19975  else
19976  // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
19977  fieldBuffer << uint32(target->GetFaction());
19978  }
19979  else
19980  fieldBuffer << m_uint32Values[index];
19981  }// pussywizard / Callmephil
19982  else if (target->IsSpectator() && target->FindMap() && target->FindMap()->IsBattleArena() &&
19983  (this->GetTypeId() == TYPEID_PLAYER || this->GetTypeId() == TYPEID_UNIT || this->GetTypeId() == TYPEID_DYNAMICOBJECT))
19984  {
19985  if (index == UNIT_FIELD_BYTES_2)
19986  fieldBuffer << (m_uint32Values[index] & 0xFFFFF2FF); // clear UNIT_BYTE2_FLAG_PVP, UNIT_BYTE2_FLAG_FFA_PVP, UNIT_BYTE2_FLAG_SANCTUARY
19987  else
19988  fieldBuffer << (uint32)target->GetFaction();
19989  }
19990  else
19991  if (!sScriptMgr->IsCustomBuildValuesUpdate(this, updateType, fieldBuffer, target, index))
19992  {
19993  fieldBuffer << m_uint32Values[index];
19994  }
19995  }
19996  else
19997  // send in current format (float as float, uint32 as uint32)
19998  fieldBuffer << m_uint32Values[index];
19999  }
20000  }
20001 
20002  *data << uint8(updateMask.GetBlockCount());
20003  updateMask.AppendToPacket(data);
20004  data->append(fieldBuffer);
20005 }
20006 
20008 {
20009  data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + 4 + 4);
20010  data << GetGUID();
20011  data << uint8(flags);
20012  data << uint32(spellId);
20013  data << uint32(cooldown);
20014 }
20015 
20017 {
20018  data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + (4 + 4) * cooldowns.size());
20019  data << GetGUID();
20020  data << uint8(flags);
20021  for (std::unordered_map<uint32, uint32>::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr)
20022  {
20023  data << uint32(itr->first);
20024  data << uint32(itr->second);
20025  }
20026 }
20027 
20028 uint8 Unit::getRace(bool original) const
20029 {
20030  if (GetTypeId() == TYPEID_PLAYER)
20031  {
20032  if (original)
20033  return m_realRace;
20034  else
20035  return m_race;
20036  }
20037 
20038  return GetByteValue(UNIT_FIELD_BYTES_0, 0);
20039 }
20040 
20042 {
20043  if (GetTypeId() == TYPEID_PLAYER)
20044  m_race = race;
20045 }
20046 
20047 // Check if unit in combat with specific unit
20048 bool Unit::IsInCombatWith(Unit const* who) const
20049 {
20050  // Check target exists
20051  if (!who)
20052  return false;
20053  // Search in threat list
20054  ObjectGuid guid = who->GetGUID();
20055  for (ThreatContainer::StorageType::const_iterator i = m_ThreatMgr.getThreatList().begin(); i != m_ThreatMgr.getThreatList().end(); ++i)
20056  {
20057  HostileReference* ref = (*i);
20058  // Return true if the unit matches
20059  if (ref && ref->getUnitGuid() == guid)
20060  return true;
20061  }
20062  // Nothing found, false.
20063  return false;
20064 }
20065 
20074 {
20075  if (GetTypeId() == TYPEID_PLAYER)
20076  return GetObjectSize();
20077 
20078  float scaleMod = GetObjectScale(); // 99% sure about this
20079  float objectSize = GetObjectSize();
20080  float defaultSize = DEFAULT_WORLD_OBJECT_SIZE * scaleMod;
20081 
20083  CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.AssertEntry(GetNativeDisplayId());
20084  CreatureModelDataEntry const* modelData = sCreatureModelDataStore.AssertEntry(displayInfo->ModelId);
20085 
20086  if (IsMounted())
20087  {
20089  {
20090  if (CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId))
20091  {
20092  if (G3D::fuzzyGt(mountModelData->CollisionWidth, modelData->CollisionWidth))
20093  modelData = mountModelData;
20094  }
20095  }
20096  }
20097 
20098  float collisionWidth = scaleMod * modelData->CollisionWidth * modelData->Scale * displayInfo->scale * 2;
20099  // if the objectSize is the default value or the creature is mounted and we have a DBC value, then we can retrieve DBC value instead
20100  return G3D::fuzzyGt(collisionWidth, 0.0f) && (G3D::fuzzyEq(objectSize,defaultSize) || IsMounted()) ? collisionWidth : objectSize;
20101 }
20102 
20111 {
20112  return GetCollisionWidth() / 2;
20113 }
20114 
20117 {
20118  float scaleMod = GetObjectScale(); // 99% sure about this
20119  float defaultHeight = DEFAULT_COLLISION_HEIGHT * scaleMod;
20120 
20121  CreatureDisplayInfoEntry const* displayInfo = sCreatureDisplayInfoStore.AssertEntry(GetNativeDisplayId());
20122  CreatureModelDataEntry const* modelData = sCreatureModelDataStore.AssertEntry(displayInfo->ModelId);
20123  float collisionHeight = 0.0f;
20124 
20125  if (IsMounted())
20126  {
20128  {
20129  if (CreatureModelDataEntry const* mountModelData = sCreatureModelDataStore.LookupEntry(mountDisplayInfo->ModelId))
20130  {
20131  collisionHeight = scaleMod * (mountModelData->MountHeight + modelData->CollisionHeight * modelData->Scale * displayInfo->scale * 0.5f);
20132  }
20133  }
20134  }
20135  else
20136  collisionHeight = scaleMod * modelData->CollisionHeight * modelData->Scale * displayInfo->scale;
20137 
20138  return collisionHeight == 0.0f ? defaultHeight : collisionHeight;
20139 }
20140 
20141 void Unit::Talk(std::string_view text, ChatMsg msgType, Language language, float textRange, WorldObject const* target)
20142 {
20143  Acore::CustomChatTextBuilder builder(this, msgType, text, language, target);
20146  Cell::VisitWorldObjects(this, worker, textRange);
20147 }
20148 
20149 void Unit::Say(std::string_view text, Language language, WorldObject const* target /*= nullptr*/)
20150 {
20151  Talk(text, CHAT_MSG_MONSTER_SAY, language, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), target);
20152 }
20153 
20154 void Unit::Yell(std::string_view text, Language language, WorldObject const* target /*= nullptr*/)
20155 {
20156  Talk(text, CHAT_MSG_MONSTER_YELL, language, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), target);
20157 }
20158 
20159 void Unit::TextEmote(std::string_view text, WorldObject const* target /*= nullptr*/, bool isBossEmote /*= false*/)
20160 {
20162 }
20163 
20164 void Unit::Whisper(std::string_view text, Language language, Player* target, bool isBossWhisper /*= false*/)
20165 {
20166  if (!target)
20167  {
20168  return;
20169  }
20170 
20171  LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
20172  WorldPacket data;
20173  ChatHandler::BuildChatPacket(data, isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, language, this, target, text, 0, "", locale);
20174  target->SendDirectMessage(&data);
20175 }
20176 
20177 void Unit::Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target)
20178 {
20179  if (!sObjectMgr->GetBroadcastText(textId))
20180  {
20181  LOG_ERROR("entities.unit", "Unit::Talk: `broadcast_text` (ID: %u) was not found", textId);
20182  return;
20183  }
20184 
20185  Acore::BroadcastTextBuilder builder(this, msgType, textId, getGender(), target);
20188  Cell::VisitWorldObjects(this, worker, textRange);
20189 }
20190 
20191 void Unit::Say(uint32 textId, WorldObject const* target /*= nullptr*/)
20192 {
20193  Talk(textId, CHAT_MSG_MONSTER_SAY, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), target);
20194 }
20195 
20196 void Unit::Yell(uint32 textId, WorldObject const* target /*= nullptr*/)
20197 {
20198  Talk(textId, CHAT_MSG_MONSTER_YELL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), target);
20199 }
20200 
20201 void Unit::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool isBossEmote /*= false*/)
20202 {
20203  Talk(textId, isBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target);
20204 }
20205 
20206 void Unit::Whisper(uint32 textId, Player* target, bool isBossWhisper /*= false*/)
20207 {
20208  if (!target)
20209  {
20210  return;
20211  }
20212 
20213  BroadcastText const* bct = sObjectMgr->GetBroadcastText(textId);
20214  if (!bct)
20215  {
20216  LOG_ERROR("entities.unit", "Unit::Whisper: `broadcast_text` was not %u found", textId);
20217  return;
20218  }
20219 
20220  LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
20221  WorldPacket data;
20222  ChatHandler::BuildChatPacket(data, isBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, LANG_UNIVERSAL, this, target, bct->GetText(locale, getGender()), 0, "", locale);
20223  target->SendDirectMessage(&data);
20224 }
#define sBattlefieldMgr
@ SCORE_DAMAGE_DONE
Definition: Battleground.h:204
@ SCORE_HEALING_DONE
Definition: Battleground.h:205
#define false
Definition: stdbool.h:16
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/macros") include(CheckCXXSourceRuns) include(CheckIncludeFiles) include(ConfigureScripts) include(ConfigureModules) include(deps/acore/cmake-utils/utils.cmake) include(src/cmake/ac_macros.cmake) include(conf/dist/config.cmake) if(EXISTS "$
Definition: CMakeLists.txt:37
NAME if(";${DISABLED_AC_MODULES};" MATCHES ";${MODULENAME};") continue() endif() if(EXISTS "$
Definition: CMakeLists.txt:68
#define sConditionMgr
Definition: ConditionMgr.h:286
@ CONDITION_SOURCE_TYPE_SPELL_PROC
Definition: ConditionMgr.h:146
std::list< Condition * > ConditionList
Definition: ConditionMgr.h:233
static First const & RAND(First const &first, Second const &second, Rest const &... rest)
@ CREATURE_FLAG_EXTRA_NO_BLOCK
Definition: CreatureData.h:50
@ CREATURE_FLAG_EXTRA_NO_CRUSHING_BLOWS
Definition: CreatureData.h:51
@ CREATURE_FLAG_EXTRA_NO_CRIT
Definition: CreatureData.h:63
@ CREATURE_FLAG_EXTRA_TRIGGER
Definition: CreatureData.h:53
@ CREATURE_FLAG_EXTRA_INSTANCE_BIND
Definition: CreatureData.h:46
@ CREATURE_FLAG_EXTRA_OBEYS_TAUNT_DIMINISHING_RETURNS
Definition: CreatureData.h:65
@ CREATURE_FLAG_EXTRA_NO_PARRY
Definition: CreatureData.h:48
@ CREATURE_FLAG_EXTRA_NO_DODGE
Definition: CreatureData.h:69
@ CREATURE_FLAG_EXTRA_ALL_DIMINISH
Definition: CreatureData.h:66
#define MAX_AGGRO_RESET_TIME
Definition: CreatureData.h:32
@ FACTION_FLAG_AT_WAR
Definition: DBCEnums.h:296
@ ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE
Definition: DBCEnums.h:158
@ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER
Definition: DBCEnums.h:127
@ ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE
Definition: DBCEnums.h:119
@ ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE
Definition: DBCEnums.h:126
@ ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS
Definition: DBCEnums.h:159
@ FACTION_TEMPLATE_FLAG_HATES_ALL_EXCEPT_FRIENDS
Definition: DBCEnums.h:320
@ FACTION_TEMPLATE_FLAG_ATTACK_PVP_ACTIVE_PLAYERS
Definition: DBCEnums.h:319
DBCStorage< VehicleEntry > sVehicleStore(VehicleEntryfmt)
DBCStorage< LiquidTypeEntry > sLiquidTypeStore(LiquidTypefmt)
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
DBCStorage< SpellShapeshiftEntry > sSpellShapeshiftStore(SpellShapeshiftfmt)
DBCStorage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore(CreatureDisplayInfofmt)
DBCStorage< CreatureModelDataEntry > sCreatureModelDataStore(CreatureModelDatafmt)
DBCStorage< FactionTemplateEntry > sFactionTemplateStore(FactionTemplateEntryfmt)
#define MAX_EFFECT_MASK
#define MAX_SPELL_EFFECTS
std::int32_t int32
Definition: Define.h:110
std::uint32_t uint32
Definition: Define.h:114
#define ABORT
Definition: Errors.h:62
#define ASSERT
Definition: Errors.h:58
@ GROUP_UPDATE_FLAG_CUR_HP
Definition: Group.h:99
@ GROUP_UPDATE_FLAG_PET_CUR_HP
Definition: Group.h:111
@ GROUP_UPDATE_FLAG_POWER_TYPE
Definition: Group.h:101
@ GROUP_UPDATE_FLAG_PET_CUR_POWER
Definition: Group.h:114
@ GROUP_UPDATE_FLAG_PET_MAX_POWER
Definition: Group.h:115
@ GROUP_UPDATE_FLAG_MAX_HP
Definition: Group.h:100
@ GROUP_UPDATE_FLAG_PET_POWER_TYPE
Definition: Group.h:113
@ GROUP_UPDATE_FLAG_MAX_POWER
Definition: Group.h:103
@ GROUP_UPDATE_FLAG_PET_AURAS
Definition: Group.h:116
@ GROUP_UPDATE_FLAG_AURAS
Definition: Group.h:107
@ GROUP_UPDATE_FLAG_LEVEL
Definition: Group.h:104
@ GROUP_UPDATE_FLAG_PET_MAX_HP
Definition: Group.h:112
@ GROUP_UPDATE_FLAG_CUR_POWER
Definition: Group.h:102
@ CONFIG_INSTANT_TAXI
Definition: IWorld.h:361
@ CONFIG_CREATURE_FAMILY_FLEE_DELAY
Definition: IWorld.h:267
@ CONFIG_CREATURE_FAMILY_ASSISTANCE_PERIOD
Definition: IWorld.h:266
@ CONFIG_DURABILITY_LOSS_IN_PVP
Definition: IWorld.h:71
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP
Definition: IWorld.h:80
@ RATE_POWER_RAGE_INCOME
Definition: IWorld.h:404
@ RATE_DURABILITY_LOSS_DAMAGE
Definition: IWorld.h:480
@ RATE_DURABILITY_LOSS_ON_DEATH
Definition: IWorld.h:479
@ CONFIG_LISTEN_RANGE_YELL
Definition: IWorld.h:184
@ CONFIG_LISTEN_RANGE_SAY
Definition: IWorld.h:182
@ CONFIG_LISTEN_RANGE_TEXTEMOTE
Definition: IWorld.h:183
EnchantmentSlot
Definition: Item.h:162
@ TEMP_ENCHANTMENT_SLOT
Definition: Item.h:164
@ ITEM_SUBCLASS_WEAPON_DAGGER
Definition: ItemTemplate.h:368
@ ITEM_SUBCLASS_WEAPON_WAND
Definition: ItemTemplate.h:372
@ INVTYPE_RANGED
Definition: ItemTemplate.h:280
@ INVTYPE_THROWN
Definition: ItemTemplate.h:290
@ INVTYPE_RANGEDRIGHT
Definition: ItemTemplate.h:291
@ INVTYPE_WEAPON
Definition: ItemTemplate.h:278
@ INVTYPE_WEAPONMAINHAND
Definition: ItemTemplate.h:286
@ INVTYPE_WEAPONOFFHAND
Definition: ItemTemplate.h:287
@ INVTYPE_2HWEAPON
Definition: ItemTemplate.h:282
@ ITEM_CLASS_ARMOR
Definition: ItemTemplate.h:304
@ ITEM_CLASS_WEAPON
Definition: ItemTemplate.h:302
LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true)
@ FREE_FOR_ALL
Definition: LootMgr.h:59
@ LIQUID_MAP_UNDER_WATER
Definition: Map.h:137
#define INVALID_HEIGHT
Definition: Map.h:155
#define MAP_LIQUID_STATUS_SWIMMING
Definition: Map.h:140
@ MOTION_SLOT_CONTROLLED
Definition: MotionMaster.h:63
@ MOTION_SLOT_ACTIVE
Definition: MotionMaster.h:62
@ ESCORT_MOTION_TYPE
Definition: MotionMaster.h:55
@ WAYPOINT_MOTION_TYPE
Definition: MotionMaster.h:39
@ FLEEING_MOTION_TYPE
Definition: MotionMaster.h:47
@ NULL_MOTION_TYPE
Definition: MotionMaster.h:56
@ CONFUSED_MOTION_TYPE
Definition: MotionMaster.h:42
@ FOLLOW_MOTION_TYPE
Definition: MotionMaster.h:52
@ NOTIFY_AI_RELOCATION
Definition: Object.h:61
@ NOTIFY_VISIBILITY_CHANGED
Definition: Object.h:62
#define MAX_VISIBILITY_DISTANCE
Definition: ObjectDefines.h:27
#define DEFAULT_COLLISION_HEIGHT
Definition: ObjectDefines.h:42
#define DEFAULT_WORLD_OBJECT_SIZE
Definition: ObjectDefines.h:37
#define NOMINAL_MELEE_RANGE
Definition: ObjectDefines.h:40
#define VISIBILITY_INC_FOR_GOBJECTS
Definition: ObjectDefines.h:28
#define DEFAULT_COMBAT_REACH
Definition: ObjectDefines.h:38
#define VISIBILITY_COMPENSATION
Definition: ObjectDefines.h:29
@ TYPEID_DYNAMICOBJECT
Definition: ObjectGuid.h:40
@ TYPEID_UNIT
Definition: ObjectGuid.h:37
@ TYPEID_PLAYER
Definition: ObjectGuid.h:38
@ TYPEMASK_UNIT
Definition: ObjectGuid.h:51
#define sObjectMgr
Definition: ObjectMgr.h:1546
std::pair< SpellClickInfoContainer::const_iterator, SpellClickInfoContainer::const_iterator > SpellClickInfoMapBounds
Definition: ObjectMgr.h:408
@ PET_SAVE_AS_CURRENT
Definition: PetDefines.h:34
#define PET_FOLLOW_DIST
Definition: PetDefines.h:202
@ HUNTER_PET
Definition: PetDefines.h:24
@ TELE_TO_WITH_PET
Definition: Player.h:800
@ TELE_TO_NOT_LEAVE_VEHICLE
Definition: Player.h:799
@ TELE_TO_SPELL
Definition: Player.h:798
@ TELE_TO_NOT_LEAVE_COMBAT
Definition: Player.h:796
@ TELE_TO_NOT_UNSUMMON_PET
Definition: Player.h:797
@ TELE_TO_NOT_LEAVE_TRANSPORT
Definition: Player.h:795
@ RUNE_DEATH
Definition: Player.h:395
@ RUNE_BLOOD
Definition: Player.h:392
#define MAX_RUNES
Definition: Player.h:381
@ PLAYER_FLAGS_CONTESTED_PVP
Definition: Player.h:465
@ PLAYER_FLAGS_UBER
Definition: Player.h:476
std::map< uint32, SpellCooldown > SpellCooldowns
Definition: Player.h:203
@ CHEAT_GOD
Definition: Player.h:969
@ DELAYED_VEHICLE_TELEPORT
Definition: Player.h:879
std::unordered_map< uint32, PlayerSpell * > PlayerSpellMap
Definition: Player.h:188
EquipmentSlots
Definition: Player.h:654
@ EQUIPMENT_SLOT_MAINHAND
Definition: Player.h:671
@ EQUIPMENT_SLOT_END
Definition: Player.h:675
@ EQUIPMENT_SLOT_OFFHAND
Definition: Player.h:672
@ EQUIPMENT_SLOT_RANGED
Definition: Player.h:673
#define INVENTORY_SLOT_BAG_0
Definition: Player.h:651
@ PLAYERSPELL_REMOVED
Definition: Player.h:117
int next(int i, int n)
#define sScriptMgr
Definition: ScriptMgr.h:2048
@ SERVERSIDE_VISIBILITY_GM
@ SERVERSIDE_VISIBILITY_GHOST
@ EFFECT_1
Definition: SharedDefines.h:31
@ EFFECT_0
Definition: SharedDefines.h:30
@ EFFECT_2
Definition: SharedDefines.h:32
@ EMOTE_ONESHOT_WOUND_CRITICAL
@ EMOTE_ONESHOT_NONE
@ EMOTE_ONESHOT_PARRY_SHIELD
#define MAX_STATS
Powers
@ POWER_RAGE
@ POWER_HEALTH
@ POWER_RUNIC_POWER
@ POWER_HAPPINESS
@ POWER_ENERGY
@ POWER_MANA
@ POWER_RUNE
@ POWER_FOCUS
DiminishingGroup
@ DIMINISHING_NONE
@ DIMINISHING_TAUNT
ChatMsg
@ CHAT_MSG_MONSTER_WHISPER
@ CHAT_MSG_RAID_BOSS_WHISPER
@ CHAT_MSG_RAID_BOSS_EMOTE
@ CHAT_MSG_MONSTER_EMOTE
@ CHAT_MSG_MONSTER_SAY
@ CHAT_MSG_MONSTER_YELL
SpellSchools
@ SPELL_SCHOOL_SHADOW
@ SPELL_SCHOOL_NORMAL
@ SPELL_SCHOOL_NATURE
@ SPELL_SCHOOL_FROST
@ SPELL_SCHOOL_ARCANE
@ SPELL_SCHOOL_FIRE
@ SPELL_SCHOOL_HOLY
@ SPELL_ATTR7_DONT_CAUSE_SPELL_PUSHBACK
@ SPELL_ATTR7_DISPEL_REMOVES_CHARGES
@ SPELL_ATTR7_NO_ATTACK_PARRY
@ SPELL_ATTR7_NO_ATTACK_MISS
@ SPELL_ATTR7_NO_ATTACK_DODGE
@ SPELL_ATTR7_DISABLE_AURA_WHILE_DEAD
@ SPELL_ATTR7_NO_TARGET_DURATION_MOD
@ SPELL_EFFECT_POWER_BURN
@ SPELL_EFFECT_HEALTH_LEECH
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_NORMALIZED_WEAPON_DMG
@ SPELL_EFFECT_DISPEL
@ SPELL_EFFECT_ADD_EXTRA_ATTACKS
@ SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
@ SPELL_EFFECT_PERSISTENT_AREA_AURA
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_ENERGIZE
@ SPELL_EFFECT_POWER_DRAIN
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ SPELL_EFFECT_APPLY_AURA
Language
@ LANG_UNIVERSAL
@ GENDER_MALE
Definition: SharedDefines.h:60
@ SPELL_ATTR5_SPELL_HASTE_AFFECTS_PERIODIC
@ SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL
@ SPELL_ATTR5_AURA_AFFECTS_NOT_JUST_REQ_EQUIPED_ITEM
@ SPELL_ATTR5_REMOVE_ENTERING_ARENA
constexpr auto MAX_SPELL_SCHOOL
@ NPC_CLICK_CAST_TARGET_CLICKER
@ NPC_CLICK_CAST_ORIG_CASTER_OWNER
@ NPC_CLICK_CAST_CASTER_CLICKER
@ SPELL_ATTR2_AUTO_REPEAT
@ SPELL_ATTR2_CANT_CRIT
@ SPELL_ATTR2_ALLOW_DEAD_TARGET
@ SPELL_ATTR2_IGNORE_LINE_OF_SIGHT
@ SPELL_ATTR2_DO_NOT_RESET_COMBAT_TIMERS
@ SPELL_ATTR2_NO_SCHOOL_IMMUNITIES
@ CREATURE_TYPE_HUMANOID
@ CREATURE_TYPE_NON_COMBAT_PET
@ CREATURE_TYPE_DEMON
@ SPELL_ATTR1_IMMUNITY_PURGES_EFFECT
@ SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS
@ SPELL_ATTR1_NO_REDIRECTION
SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask)
uint32 const CREATURE_TYPEMASK_DEMON_OR_UNDEAD
@ UNIT_DYNFLAG_SPECIALINFO
@ UNIT_DYNFLAG_TAPPED_BY_PLAYER
@ UNIT_DYNFLAG_TAPPED
@ UNIT_DYNFLAG_LOOTABLE
@ UNIT_DYNFLAG_TRACK_UNIT
@ SPELL_ATTR3_TREAT_AS_PERIODIC
@ SPELL_ATTR3_ALLOW_AURA_WHILE_DEAD
@ SPELL_ATTR3_ALWAYS_HIT
@ SPELL_ATTR3_NO_PROC_EQUIP_REQUIREMENT
@ SPELL_ATTR3_INSTANT_TARGET_PROCS
@ SPELL_ATTR3_COMPLETELY_BLOCKED
@ SPELL_ATTR3_IGNORE_CASTER_MODIFIERS
@ SPELL_DAMAGE_CLASS_RANGED
@ SPELL_DAMAGE_CLASS_MAGIC
@ SPELL_DAMAGE_CLASS_NONE
@ SPELL_DAMAGE_CLASS_MELEE
@ TEAM_ALLIANCE
@ TEAM_HORDE
@ AI_REACTION_HOSTILE
@ DUEL_FLED
@ DUEL_WON
@ DUEL_INTERRUPTED
@ SUMMON_TYPE_MINIPET
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_DEATH_KNIGHT
@ CLASS_PALADIN
@ CLASS_ROGUE
#define PER_CASTER_AURA_STATE_MASK
@ MECHANIC_SLOW_ATTACK
@ MECHANIC_ENRAGED
@ MECHANIC_FEAR
@ MECHANIC_DISORIENTED
@ MECHANIC_KNOCKOUT
@ MECHANIC_STUN
@ MECHANIC_ROOT
@ MECHANIC_BLEED
@ MECHANIC_SNARE
@ MECHANIC_SILENCE
@ IMMUNITY_STATE
@ IMMUNITY_ALLOW_ID
@ IMMUNITY_EFFECT
@ IMMUNITY_ID
@ IMMUNITY_DAMAGE
@ IMMUNITY_MECHANIC
@ IMMUNITY_SCHOOL
@ IMMUNITY_DISPEL
SpellFamilyNames
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_GENERIC
@ SPELLFAMILY_WARRIOR
@ SPELLFAMILY_PALADIN
@ SPELLFAMILY_HUNTER
@ SPELLFAMILY_POTION
@ SPELLFAMILY_ROGUE
@ SPELLFAMILY_SHAMAN
@ SPELLFAMILY_DRUID
@ SPELLFAMILY_PET
@ SPELLFAMILY_DEATHKNIGHT
@ SPELL_ATTR0_NO_ACTIVE_DEFENSE
@ SPELL_ATTR0_PASSIVE
@ SPELL_ATTR0_IS_ABILITY
@ SPELL_ATTR0_NO_IMMUNITIES
ReputationRank
@ REP_HATED
@ REP_EXALTED
@ REP_FRIENDLY
@ REP_NEUTRAL
@ REP_HOSTILE
@ GHOST_VISIBILITY_ALIVE
@ SPELL_HIT_TYPE_UNK1
@ SPELL_HIT_TYPE_CRIT
@ SPELL_HIT_TYPE_UNK3
@ SPELL_HIT_TYPE_UNK6
@ RACE_TROLL
Definition: SharedDefines.h:77
@ RACE_ORC
Definition: SharedDefines.h:71
@ RACE_DRAENEI
Definition: SharedDefines.h:80
@ RACE_NIGHTELF
Definition: SharedDefines.h:73
@ RACE_DWARF
Definition: SharedDefines.h:72
@ RACE_TAUREN
Definition: SharedDefines.h:75
SpellMissInfo
@ SPELL_MISS_PARRY
@ SPELL_MISS_IMMUNE
@ SPELL_MISS_ABSORB
@ SPELL_MISS_DODGE
@ SPELL_MISS_IMMUNE2
@ SPELL_MISS_NONE
@ SPELL_MISS_RESIST
@ SPELL_MISS_MISS
@ SPELL_MISS_EVADE
@ SPELL_MISS_REFLECT
@ SPELL_MISS_BLOCK
@ SPELL_MISS_DEFLECT
AuraStateType
@ AURA_STATE_DEFENSE
@ AURA_STATE_FROZEN
@ AURA_STATE_BLEEDING
@ AURA_STATE_FAERIE_FIRE
@ AURA_STATE_ENRAGE
@ AURA_STATE_HEALTHLESS_35_PERCENT
@ AURA_STATE_HEALTH_ABOVE_75_PERCENT
@ AURA_STATE_HEALTHLESS_20_PERCENT
@ AURA_STATE_CONFLAGRATE
@ AURA_STATE_HUNTER_PARRY
#define EFFECT_ALL
Definition: SharedDefines.h:37
@ DRTYPE_PLAYER
@ DRTYPE_ALL
Stats
@ STAT_SPIRIT
@ STAT_INTELLECT
@ STAT_AGILITY
@ STAT_STRENGTH
@ STAT_STAMINA
DispelType
@ DISPEL_MAGIC
@ DISPEL_DISEASE
SpellCastResult
@ SPELL_FAILED_NO_POWER
@ SPELL_FAILED_OUT_OF_RANGE
@ SPELL_CAST_OK
@ SPELL_FAILED_LINE_OF_SIGHT
@ SPELL_FAILED_SPELL_UNAVAILABLE
#define MAX_SPELL_IMMUNITY
@ SPELL_ATTR4_OWNER_POWER_SCALING
@ SPELL_ATTR4_ALLOW_ENETRING_ARENA
@ SPELL_ATTR4_NO_CAST_LOG
@ SPELL_ATTR4_REACTIVE_DAMAGE_PROC
@ CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT
@ CREATURE_TYPE_FLAG_CAN_ASSIST
@ CREATURE_TYPE_FLAG_ALLOW_MOUNTED_COMBAT
@ SKILL_DEFENSE
@ SKILL_UNARMED
@ SPELL_ATTR6_CAN_TARGET_UNTARGETABLE
@ SPELL_ATTR6_IGNORE_HEALTH_MODIFIERS
@ SPELL_ATTR6_IGNORE_CASTER_DAMAGE_MODIFIERS
@ SPELL_ATTR6_IGNORE_PHASE_SHIFT
@ SPELL_ATTR6_DO_NOT_CONSUME_RESOURCES
@ SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC
SpellSchoolMask
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_MAGIC
@ SPELL_SCHOOL_MASK_NATURE
@ SPELL_SCHOOL_MASK_HOLY
@ SPELL_SCHOOL_MASK_FIRE
@ SPELL_SCHOOL_MASK_FROST
@ SPELL_STATE_DELAYED
Definition: Spell.h:228
@ SPELL_STATE_FINISHED
Definition: Spell.h:226
@ SPELL_STATE_PREPARING
Definition: Spell.h:224
@ SPELL_STATE_CASTING
Definition: Spell.h:225
#define MAX_AURAS
AuraType
@ SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS
@ SPELL_AURA_MANA_SHIELD
@ SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
@ SPELL_AURA_CLONE_CASTER
@ SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK
@ SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL
@ SPELL_AURA_MOD_ATTACK_POWER
@ SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE
@ SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
@ SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
@ SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS
@ SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER
@ SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE
@ SPELL_AURA_MOD_PARRY_PERCENT
@ SPELL_AURA_ABILITY_IGNORE_AURASTATE
@ SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE
@ SPELL_AURA_MOD_IGNORE_TARGET_RESIST
@ SPELL_AURA_MOD_SHAPESHIFT
@ SPELL_AURA_MOD_DAMAGE_DONE_VERSUS
@ SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT
@ SPELL_AURA_DAMAGE_SHIELD
@ SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
@ SPELL_AURA_OBS_MOD_HEALTH
@ SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK
@ SPELL_AURA_MOD_THREAT
@ SPELL_AURA_PERIODIC_HEALTH_FUNNEL
@ TOTAL_AURAS
@ SPELL_AURA_PERIODIC_MANA_LEECH
@ SPELL_AURA_MOD_DEBUFF_RESISTANCE
@ SPELL_AURA_MOD_POSSESS_PET
@ SPELL_AURA_MOD_INCREASE_SPEED
@ SPELL_AURA_MOD_RESISTANCE
@ SPELL_AURA_MOD_EXPERTISE
@ SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_HASTE_SPELLS
@ SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER
@ SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE
@ SPELL_AURA_MOD_FEAR
@ SPELL_AURA_MOD_POWER_REGEN
@ SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
@ SPELL_AURA_MOD_HEALING_DONE_PERCENT
@ SPELL_AURA_LINKED
@ SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS
@ SPELL_AURA_SHARE_DAMAGE_PCT
@ SPELL_AURA_OBS_MOD_POWER
@ SPELL_AURA_ADD_CASTER_HIT_TRIGGER
@ SPELL_AURA_SPLIT_DAMAGE_FLAT
@ SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
@ SPELL_AURA_REFLECT_SPELLS
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_IGNORE_HIT_DIRECTION
@ SPELL_AURA_IGNORE_COMBAT_RESULT
@ SPELL_AURA_MOD_MELEE_HASTE
@ SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_SPIRIT_OF_REDEMPTION
@ SPELL_AURA_EMPATHY
@ SPELL_AURA_MOD_SPEED_NOT_STACK
@ SPELL_AURA_MOD_STALKED
@ SPELL_AURA_SCHOOL_HEAL_ABSORB
@ SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED
@ SPELL_AURA_MOD_SPELL_CRIT_CHANCE
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_MOD_ENEMY_DODGE
@ SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
@ SPELL_AURA_PERIODIC_DAMAGE_PERCENT
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
@ SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL
@ SPELL_AURA_MOD_DODGE_PERCENT
@ SPELL_AURA_MOD_INCREASE_SWIM_SPEED
@ SPELL_AURA_FLY
@ SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
@ SPELL_AURA_ADD_TARGET_TRIGGER
@ SPELL_AURA_SPLIT_DAMAGE_PCT
@ SPELL_AURA_DEFLECT_SPELLS
@ SPELL_AURA_MOD_CRIT_DAMAGE_BONUS
@ SPELL_AURA_MOD_HEALING_DONE
@ SPELL_AURA_MOD_HEALING_RECEIVED
@ SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
@ SPELL_AURA_MOD_HEALING_PCT
@ SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
@ SPELL_AURA_MOD_CHARM
@ SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT
@ SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE
@ SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT
@ SPELL_AURA_MOD_ARMOR_PENETRATION_PCT
@ SPELL_AURA_MOD_ROOT
@ SPELL_AURA_MECHANIC_DURATION_MOD
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
@ SPELL_AURA_MOD_POWER_COST_SCHOOL
@ SPELL_AURA_MECHANIC_IMMUNITY
@ SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE
@ SPELL_AURA_RAID_PROC_FROM_CHARGE
@ SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN
@ SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT
@ SPELL_AURA_MOD_DAMAGE_TAKEN
@ SPELL_AURA_MOD_TAUNT
@ SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE
@ SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS
@ SPELL_AURA_PHASE
@ SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE
@ SPELL_AURA_MOD_CRIT_PCT
@ SPELL_AURA_MOD_MINIMUM_SPEED
@ SPELL_AURA_MOD_BLOCK_CRIT_CHANCE
@ SPELL_AURA_MOD_HOT_PCT
@ SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT
@ SPELL_AURA_AOE_CHARM
@ SPELL_AURA_MOD_TARGET_RESISTANCE
@ SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS
@ SPELL_AURA_MOD_SPEED_ALWAYS
@ SPELL_AURA_MOD_DECREASE_SPEED
@ SPELL_AURA_TRANSFORM
@ SPELL_AURA_SCHOOL_ABSORB
@ SPELL_AURA_REDUCE_PUSHBACK
@ SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
@ SPELL_AURA_PERIODIC_ENERGIZE
@ SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
@ SPELL_AURA_MOD_WEAPON_CRIT_PERCENT
@ SPELL_AURA_MOD_DAMAGE_DONE_CREATURE
@ SPELL_AURA_SPELL_MAGNET
@ SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL
@ SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER
@ SPELL_AURA_PERIODIC_LEECH
@ SPELL_AURA_PROC_TRIGGER_DAMAGE
@ SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE
@ SPELL_AURA_MOD_DAMAGE_FROM_CASTER
@ SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT
@ SPELL_AURA_DAMAGE_IMMUNITY
@ SPELL_AURA_MOD_HEALING
@ SPELL_AURA_MOD_DAMAGE_DONE
@ SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST
@ SPELL_AURA_MOD_AOE_AVOIDANCE
@ SPELL_AURA_MOD_CONFUSE
@ SPELL_AURA_MOD_POSSESS
@ SPELL_AURA_REFLECT_SPELLS_SCHOOL
@ SPELL_AURA_PERIODIC_DUMMY
@ SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT
@ SPELL_AURA_MOD_MECHANIC_RESISTANCE
@ SPELL_AURA_MOD_UNATTACKABLE
@ SPELL_AURA_MOD_STEALTH
@ SPELL_AURA_NONE
@ SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
@ SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@ SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
@ SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
@ SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
@ SPELL_AURA_IGNORED
@ SPELL_AURA_MOD_BLOCK_PERCENT
@ SPELL_AURA_MOD_STUN
@ SPELL_AURA_BIND_SIGHT
@ AURA_EFFECT_HANDLE_STAT
@ AURA_EFFECT_HANDLE_REAL
@ AURA_EFFECT_HANDLE_SEND_FOR_CLIENT
@ UNIT_AURA_TYPE
@ SPELL_ATTR0_CU_IGNORE_ARMOR
Definition: SpellInfo.h:191
@ SPELL_ATTR0_CU_ENCHANT_PROC
Definition: SpellInfo.h:176
@ SPELL_ATTR0_CU_NO_POSITIVE_TAKEN_BONUS
Definition: SpellInfo.h:197
@ SPELL_ATTR0_CU_DIRECT_DAMAGE
Definition: SpellInfo.h:184
@ SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET
Definition: SpellInfo.h:193
@ SPELL_ATTR0_CU_SINGLE_AURA_STACK
Definition: SpellInfo.h:198
@ SPELL_ATTR0_CU_AURA_CC
Definition: SpellInfo.h:181
@ SPELL_ATTR0_CU_BINARY_SPELL
Definition: SpellInfo.h:196
@ SPELL_ATTR0_CU_SCHOOLMASK_NORMAL_WITH_MAGIC
Definition: SpellInfo.h:199
@ SPELL_SPECIFIC_MAGE_POLYMORPH
Definition: SpellInfo.h:160
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
Definition: SpellMgr.cpp:246
DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group)
Definition: SpellMgr.cpp:265
#define MELEE_BASED_TRIGGER_MASK
Definition: SpellMgr.h:182
#define sSpellMgr
Definition: SpellMgr.h:794
@ PROC_EX_NONE
Definition: SpellMgr.h:193
@ PROC_EX_DODGE
Definition: SpellMgr.h:198
@ PROC_EX_DEFLECT
Definition: SpellMgr.h:203
@ PROC_EX_BLOCK
Definition: SpellMgr.h:200
@ PROC_EX_INTERNAL_CANT_PROC
Definition: SpellMgr.h:218
@ PROC_EX_CRITICAL_HIT
Definition: SpellMgr.h:195
@ PROC_EX_NORMAL_HIT
Definition: SpellMgr.h:194
@ PROC_EX_IMMUNE
Definition: SpellMgr.h:202
@ PROC_EX_MISS
Definition: SpellMgr.h:196
@ PROC_EX_INTERNAL_HOT
Definition: SpellMgr.h:220
@ PROC_EX_RESIST
Definition: SpellMgr.h:197
@ PROC_EX_REFLECT
Definition: SpellMgr.h:205
@ PROC_EX_FULL_BLOCK
Definition: SpellMgr.h:207
@ PROC_EX_ABSORB
Definition: SpellMgr.h:204
@ PROC_EX_PARRY
Definition: SpellMgr.h:199
@ PROC_EX_INTERNAL_TRIGGERED
Definition: SpellMgr.h:221
@ PROC_EX_EVADE
Definition: SpellMgr.h:201
@ PROC_EX_INTERNAL_REQ_FAMILY
Definition: SpellMgr.h:222
@ PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS
Definition: SpellMgr.h:119
@ PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
Definition: SpellMgr.h:128
@ PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK
Definition: SpellMgr.h:117
@ PROC_FLAG_DONE_PERIODIC
Definition: SpellMgr.h:134
@ PROC_FLAG_DONE_MELEE_AUTO_ATTACK
Definition: SpellMgr.h:110
@ PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS
Definition: SpellMgr.h:122
@ PROC_FLAG_KILLED
Definition: SpellMgr.h:107
@ PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS
Definition: SpellMgr.h:113
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
Definition: SpellMgr.h:132
@ PROC_FLAG_DEATH
Definition: SpellMgr.h:143
@ PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS
Definition: SpellMgr.h:120
@ PROC_FLAG_TAKEN_PERIODIC
Definition: SpellMgr.h:135
@ PROC_FLAG_KILL
Definition: SpellMgr.h:108
@ PROC_FLAG_DONE_MAINHAND_ATTACK
Definition: SpellMgr.h:140
@ PROC_FLAG_DONE_RANGED_AUTO_ATTACK
Definition: SpellMgr.h:116
@ PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG
Definition: SpellMgr.h:126
@ PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG
Definition: SpellMgr.h:125
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS
Definition: SpellMgr.h:129
@ PROC_FLAG_TAKEN_DAMAGE
Definition: SpellMgr.h:137
@ PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK
Definition: SpellMgr.h:111
@ PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS
Definition: SpellMgr.h:123
@ PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS
Definition: SpellMgr.h:114
@ PROC_FLAG_DONE_OFFHAND_ATTACK
Definition: SpellMgr.h:141
@ PROC_FLAG_NONE
Definition: SpellMgr.h:105
@ PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG
Definition: SpellMgr.h:131
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition: Timer.h:40
@ TOTEM_PASSIVE
Definition: Totem.h:25
static bool procPrepared
Definition: Unit.cpp:112
float baseMoveSpeed[MAX_MOVE_TYPE]
Definition: Unit.cpp:77
static bool isAlwaysTriggeredAura[TOTAL_AURAS]
Definition: Unit.cpp:110
static bool InitTriggerAuraData()
Definition: Unit.cpp:15232
static bool isNonTriggerAura[TOTAL_AURAS]
Definition: Unit.cpp:108
void createProcFlags(const SpellInfo *spellInfo, WeaponAttackType attackType, bool positive, uint32 &procAttacker, uint32 &procVictim)
Definition: Unit.cpp:15292
static bool isTriggerAura[TOTAL_AURAS]
Definition: Unit.cpp:106
std::list< ProcTriggeredData > ProcTriggeredList
Definition: Unit.cpp:15226
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition)
Definition: Unit.cpp:15366
float playerBaseMoveSpeed[MAX_MOVE_TYPE]
Definition: Unit.cpp:90
@ CHANNEL_FLAG_DELAY
Definition: Unit.h:47
#define MAX_SPELL_CHARM
Definition: Unit.h:266
@ AURA_INTERRUPT_FLAG_TAKE_DAMAGE
Definition: Unit.h:53
@ AURA_INTERRUPT_FLAG_DIRECT_DAMAGE
Definition: Unit.h:76
@ AURA_INTERRUPT_FLAG_MOVE
Definition: Unit.h:55
@ AURA_INTERRUPT_FLAG_TURNING
Definition: Unit.h:56
@ AURA_INTERRUPT_FLAG_NOT_ABOVEWATER
Definition: Unit.h:59
@ AURA_INTERRUPT_FLAG_NOT_SEATED
Definition: Unit.h:70
@ AURA_INTERRUPT_FLAG_NOT_UNDERWATER
Definition: Unit.h:60
@ AURA_INTERRUPT_FLAG_MELEE_ATTACK
Definition: Unit.h:64
@ AURA_INTERRUPT_FLAG_LEAVE_COMBAT
Definition: Unit.h:78
@ AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT
Definition: Unit.h:75
@ AURA_INTERRUPT_FLAG_MOUNT
Definition: Unit.h:69
@ AURA_INTERRUPT_FLAG_NOT_MOUNTED
Definition: Unit.h:58
MovementFlags
Definition: Unit.h:698
@ MOVEMENTFLAG_SPLINE_ENABLED
Definition: Unit.h:727
@ MOVEMENTFLAG_FORWARD
Definition: Unit.h:700
@ MOVEMENTFLAG_ONTRANSPORT
Definition: Unit.h:709
@ MOVEMENTFLAG_BACKWARD
Definition: Unit.h:701
@ MOVEMENTFLAG_WATERWALKING
Definition: Unit.h:728
@ MOVEMENTFLAG_MASK_MOVING
Definition: Unit.h:733
@ MOVEMENTFLAG_DISABLE_GRAVITY
Definition: Unit.h:710
@ MOVEMENTFLAG_FLYING
Definition: Unit.h:725
@ MOVEMENTFLAG_FALLING_SLOW
Definition: Unit.h:729
@ MOVEMENTFLAG_CAN_FLY
Definition: Unit.h:724
@ MOVEMENTFLAG_ROOT
Definition: Unit.h:711
@ MOVEMENTFLAG_FALLING
Definition: Unit.h:712
@ MOVEMENTFLAG_MASK_MOVING_FLY
Definition: Unit.h:741
@ MOVEMENTFLAG_FALLING_FAR
Definition: Unit.h:713
@ MOVEMENTFLAG_SWIMMING
Definition: Unit.h:721
@ MOVEMENTFLAG_HOVER
Definition: Unit.h:730
@ MOVEMENTFLAG_SPLINE_ELEVATION
Definition: Unit.h:726
@ MOVEMENTFLAG_PENDING_ROOT
Definition: Unit.h:720
@ MOVEMENTFLAG_WALKING
Definition: Unit.h:708
@ UNIT_MASK_NONE
Definition: Unit.h:822
@ UNIT_MASK_CONTROLABLE_GUARDIAN
Definition: Unit.h:831
@ UNIT_MASK_ACCESSORY
Definition: Unit.h:832
@ UNIT_MASK_VEHICLE
Definition: Unit.h:828
@ UNIT_MASK_GUARDIAN
Definition: Unit.h:825
@ UNIT_MASK_MINION
Definition: Unit.h:824
#define WORLD_TRIGGER
Definition: Unit.h:31
#define MAX_UNIT_ACTION_BAR_INDEX
Definition: Unit.h:1219
WeaponAttackType
Definition: Unit.h:554
@ OFF_ATTACK
Definition: Unit.h:556
@ MAX_ATTACK
Definition: Unit.h:558
@ BASE_ATTACK
Definition: Unit.h:555
@ RANGED_ATTACK
Definition: Unit.h:557
VictimState
Definition: Unit.h:274
@ VICTIMSTATE_INTACT
Definition: Unit.h:275
@ VICTIMSTATE_HIT
Definition: Unit.h:276
@ VICTIMSTATE_DODGE
Definition: Unit.h:277
@ VICTIMSTATE_IS_IMMUNE
Definition: Unit.h:282
@ VICTIMSTATE_PARRY
Definition: Unit.h:278
@ VICTIMSTATE_BLOCKS
Definition: Unit.h:280
@ VICTIMSTATE_EVADES
Definition: Unit.h:281
@ SPELLMOD_EFFECT2
Definition: Unit.h:97
@ SPELLMOD_DAMAGE
Definition: Unit.h:85
@ SPELLMOD_CHANCE_OF_SUCCESS
Definition: Unit.h:103
@ SPELLMOD_CRIT_DAMAGE_BONUS
Definition: Unit.h:100
@ SPELLMOD_DOT
Definition: Unit.h:107
@ SPELLMOD_ALL_EFFECTS
Definition: Unit.h:93
@ SPELLMOD_CRITICAL_CHANCE
Definition: Unit.h:92
@ SPELLMOD_BONUS_MULTIPLIER
Definition: Unit.h:109
@ SPELLMOD_EFFECT3
Definition: Unit.h:108
@ SPELLMOD_PROC_PER_MINUTE
Definition: Unit.h:111
@ SPELLMOD_IGNORE_ARMOR
Definition: Unit.h:98
@ SPELLMOD_EFFECT1
Definition: Unit.h:88
@ SPELLMOD_CASTING_TIME
Definition: Unit.h:95
@ SPELLMOD_RESIST_MISS_CHANCE
Definition: Unit.h:101
SplineFlags
Definition: Unit.h:775
#define SUMMON_SLOT_MINIPET
Definition: Unit.h:1339
WeaponDamageRange
Definition: Unit.h:379
@ MINDAMAGE
Definition: Unit.h:380
@ MAXDAMAGE
Definition: Unit.h:381
SpellValueMod
Definition: Unit.h:121
@ SPELLVALUE_BASE_POINT1
Definition: Unit.h:123
@ SPELLVALUE_BASE_POINT2
Definition: Unit.h:124
@ SPELLVALUE_BASE_POINT0
Definition: Unit.h:122
UnitMods
Definition: Unit.h:420
@ UNIT_MOD_DAMAGE_OFFHAND
Definition: Unit.h:444
@ UNIT_MOD_RUNE
Definition: Unit.h:432
@ UNIT_MOD_STAT_INTELLECT
Definition: Unit.h:424
@ UNIT_MOD_STAT_SPIRIT
Definition: Unit.h:425
@ UNIT_MOD_ARMOR
Definition: Unit.h:434
@ UNIT_MOD_RESISTANCE_SHADOW
Definition: Unit.h:439
@ UNIT_MOD_RESISTANCE_FROST
Definition: Unit.h:438
@ UNIT_MOD_END
Definition: Unit.h:446
@ UNIT_MOD_ATTACK_POWER
Definition: Unit.h:441
@ UNIT_MOD_RESISTANCE_HOLY
Definition: Unit.h:435
@ UNIT_MOD_RESISTANCE_ARCANE
Definition: Unit.h:440
@ UNIT_MOD_ENERGY
Definition: Unit.h:430
@ UNIT_MOD_HEALTH
Definition: Unit.h:426
@ UNIT_MOD_DAMAGE_RANGED
Definition: Unit.h:445
@ UNIT_MOD_RESISTANCE_FIRE
Definition: Unit.h:436
@ UNIT_MOD_STAT_STRENGTH
Definition: Unit.h:421
@ UNIT_MOD_RESISTANCE_NATURE
Definition: Unit.h:437
@ UNIT_MOD_STAT_AGILITY
Definition: Unit.h:422
@ UNIT_MOD_FOCUS
Definition: Unit.h:429
@ UNIT_MOD_DAMAGE_MAINHAND
Definition: Unit.h:443
@ UNIT_MOD_HAPPINESS
Definition: Unit.h:431
@ UNIT_MOD_MANA
Definition: Unit.h:427
@ UNIT_MOD_STAT_START
Definition: Unit.h:448
@ UNIT_MOD_RAGE
Definition: Unit.h:428
@ UNIT_MOD_STAT_STAMINA
Definition: Unit.h:423
@ UNIT_MOD_RUNIC_POWER
Definition: Unit.h:433
@ UNIT_MOD_ATTACK_POWER_RANGED
Definition: Unit.h:442
HitInfo
Definition: Unit.h:287
@ HITINFO_PARTIAL_ABSORB
Definition: Unit.h:295
@ HITINFO_FULL_RESIST
Definition: Unit.h:296
@ HITINFO_NORMALSWING
Definition: Unit.h:288
@ HITINFO_BLOCK
Definition: Unit.h:302
@ HITINFO_CRUSHING
Definition: Unit.h:306
@ HITINFO_SWINGNOHITSOUND
Definition: Unit.h:310
@ HITINFO_MISS
Definition: Unit.h:293
@ HITINFO_RAGE_GAIN
Definition: Unit.h:312
@ HITINFO_FULL_ABSORB
Definition: Unit.h:294
@ HITINFO_OFFHAND
Definition: Unit.h:291
@ HITINFO_UNK1
Definition: Unit.h:289
@ HITINFO_GLANCING
Definition: Unit.h:305
@ HITINFO_CRITICALHIT
Definition: Unit.h:298
@ HITINFO_PARTIAL_RESIST
Definition: Unit.h:297
@ HITINFO_AFFECTS_VICTIM
Definition: Unit.h:290
@ ACTION_BAR_INDEX_PET_SPELL_START
Definition: Unit.h:1214
@ ACTION_BAR_INDEX_PET_SPELL_END
Definition: Unit.h:1215
@ ACTION_BAR_INDEX_END
Definition: Unit.h:1216
@ ACTION_BAR_INDEX_START
Definition: Unit.h:1213
#define MAX_AGGRO_RADIUS
Definition: Unit.h:271
DeathState
Definition: Unit.h:474
@ DEAD
Definition: Unit.h:478
@ ALIVE
Definition: Unit.h:475
@ JUST_RESPAWNED
Definition: Unit.h:479
@ JUST_DIED
Definition: Unit.h:476
#define CURRENT_FIRST_NON_MELEE_SPELL
Definition: Unit.h:1112
#define MAX_MOVE_TYPE
Definition: Unit.h:548
@ COMMAND_ATTACK
Definition: Unit.h:1160
@ COMMAND_FOLLOW
Definition: Unit.h:1159
@ UNIT_STAND_STATE_SLEEP
Definition: Unit.h:165
@ UNIT_STAND_STATE_SIT_HIGH_CHAIR
Definition: Unit.h:168
@ UNIT_STAND_STATE_SIT_MEDIUM_CHAIR
Definition: Unit.h:167
@ UNIT_STAND_STATE_SIT_LOW_CHAIR
Definition: Unit.h:166
@ UNIT_STAND_STATE_KNEEL
Definition: Unit.h:170
@ UNIT_STAND_STATE_SIT_CHAIR
Definition: Unit.h:164
@ UNIT_STAND_STATE_STAND
Definition: Unit.h:162
@ UNIT_STAND_STATE_SIT
Definition: Unit.h:163
#define MAX_SUMMON_SLOT
Definition: Unit.h:1341
SpellImmuneBlockType
Definition: Unit.h:353
@ SPELL_BLOCK_TYPE_ALL
Definition: Unit.h:354
AuraRemoveMode
Definition: Unit.h:385
@ AURA_REMOVE_BY_DEFAULT
Definition: Unit.h:387
@ AURA_REMOVE_BY_DEATH
Definition: Unit.h:391
@ AURA_REMOVE_BY_EXPIRE
Definition: Unit.h:390
@ AURA_REMOVE_BY_ENEMY_SPELL
Definition: Unit.h:389
TriggerCastFlags
Definition: Unit.h:395
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
Definition: Unit.h:413
@ TRIGGERED_NO_PERIODIC_RESET
Will ignore equipped item requirements.
Definition: Unit.h:415
@ TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE
Will ignore caster aura states including combat requirements and death state.
Definition: Unit.h:409
@ TRIGGERED_NONE
Definition: Unit.h:396
#define ATTACK_DISPLAY_DELAY
Definition: Unit.h:1364
UnitModifierType
Definition: Unit.h:370
@ MODIFIER_TYPE_END
Definition: Unit.h:375
@ BASE_VALUE
Definition: Unit.h:371
@ TOTAL_VALUE
Definition: Unit.h:373
@ TOTAL_PCT
Definition: Unit.h:374
@ BASE_PCT
Definition: Unit.h:372
#define CURRENT_MAX_SPELL
Definition: Unit.h:1113
CombatRating
Definition: Unit.h:562
@ CR_WEAPON_SKILL_RANGED
Definition: Unit.h:585
@ CR_CRIT_TAKEN_RANGED
Definition: Unit.h:578
@ CR_CRIT_TAKEN_SPELL
Definition: Unit.h:579
@ CR_ARMOR_PENETRATION
Definition: Unit.h:587
@ CR_HIT_TAKEN_SPELL
Definition: Unit.h:576
@ CR_WEAPON_SKILL
Definition: Unit.h:563
@ CR_WEAPON_SKILL_OFFHAND
Definition: Unit.h:584
@ CR_DEFENSE_SKILL
Definition: Unit.h:564
@ CR_WEAPON_SKILL_MAINHAND
Definition: Unit.h:583
@ CR_CRIT_TAKEN_MELEE
Definition: Unit.h:577
DiminishingLevels
Definition: Unit.h:841
@ DIMINISHING_LEVEL_3
Definition: Unit.h:844
@ DIMINISHING_LEVEL_1
Definition: Unit.h:842
@ DIMINISHING_LEVEL_4
Definition: Unit.h:846
@ DIMINISHING_LEVEL_IMMUNE
Definition: Unit.h:845
@ DIMINISHING_LEVEL_TAUNT_IMMUNE
Definition: Unit.h:847
@ DIMINISHING_LEVEL_2
Definition: Unit.h:843
@ UNIT_BYTES_1_OFFSET_ANIM_TIER
Definition: Unit.h:156
@ UNIT_BYTES_1_OFFSET_STAND_STATE
Definition: Unit.h:153
@ UNIT_NPC_FLAG_GOSSIP
Definition: Unit.h:668
@ UNIT_NPC_FLAG_SPELLCLICK
Definition: Unit.h:692
@ UNIT_NPC_FLAG_PLAYER_VEHICLE
Definition: Unit.h:693
@ UNIT_NPC_FLAG_FLIGHTMASTER
Definition: Unit.h:681
@ UNIT_NPC_FLAG_TRAINER
Definition: Unit.h:672
ShapeshiftForm
Definition: Unit.h:198
@ FORM_DIREBEAR
Definition: Unit.h:207
@ FORM_FLIGHT_EPIC
Definition: Unit.h:224
@ FORM_MOONKIN
Definition: Unit.h:228
@ FORM_NONE
Definition: Unit.h:199
@ FORM_CAT
Definition: Unit.h:200
@ FORM_FLIGHT
Definition: Unit.h:226
@ FORM_GHOSTWOLF
Definition: Unit.h:215
@ FORM_TREE
Definition: Unit.h:201
@ FORM_BEAR
Definition: Unit.h:204
#define BASE_MAXDAMAGE
Definition: Unit.h:148
CharmType
Definition: Unit.h:1202
@ CHARM_TYPE_CHARM
Definition: Unit.h:1203
@ CHARM_TYPE_POSSESS
Definition: Unit.h:1204
@ CHARM_TYPE_CONVERT
Definition: Unit.h:1206
@ CHARM_TYPE_VEHICLE
Definition: Unit.h:1205
CurrentSpellTypes
Definition: Unit.h:1105
@ CURRENT_CHANNELED_SPELL
Definition: Unit.h:1108
@ CURRENT_GENERIC_SPELL
Definition: Unit.h:1107
@ CURRENT_MELEE_SPELL
Definition: Unit.h:1106
@ CURRENT_AUTOREPEAT_SPELL
Definition: Unit.h:1109
MeleeHitOutcome
Definition: Unit.h:863
@ MELEE_HIT_CRUSHING
Definition: Unit.h:865
@ MELEE_HIT_BLOCK
Definition: Unit.h:864
@ MELEE_HIT_CRIT
Definition: Unit.h:865
@ MELEE_HIT_NORMAL
Definition: Unit.h:865
@ MELEE_HIT_EVADE
Definition: Unit.h:864
@ MELEE_HIT_DODGE
Definition: Unit.h:864
@ MELEE_HIT_MISS
Definition: Unit.h:864
@ MELEE_HIT_PARRY
Definition: Unit.h:864
@ MELEE_HIT_GLANCING
Definition: Unit.h:865
@ SPELL_INTERRUPT_FLAG_ABORT_ON_DMG
Definition: Unit.h:39
@ SPELL_INTERRUPT_FLAG_PUSH_BACK
Definition: Unit.h:36
ReactiveType
Definition: Unit.h:1329
@ REACTIVE_OVERPOWER
Definition: Unit.h:1332
@ REACTIVE_DEFENSE
Definition: Unit.h:1330
@ REACTIVE_HUNTER_PARRY
Definition: Unit.h:1331
std::list< std::pair< Aura *, uint8 > > DispelChargesList
Definition: Unit.h:350
static constexpr uint32 MAX_CREATURE_SPELLS
Definition: Unit.h:262
std::unordered_map< uint32, uint32 > PacketCooldowns
Definition: Unit.h:1361
@ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING
Definition: Unit.h:761
@ MOVEMENTFLAG2_INTERPOLATED_MOVEMENT
Definition: Unit.h:766
ActiveStates
Definition: Unit.h:1140
@ ACT_REACTION
Definition: Unit.h:1145
@ ACT_DECIDE
Definition: Unit.h:1146
@ ACT_COMMAND
Definition: Unit.h:1144
@ ACT_ENABLED
Definition: Unit.h:1143
@ ACT_PASSIVE
Definition: Unit.h:1141
@ ACT_DISABLED
Definition: Unit.h:1142
#define MAX_REACTIVE
Definition: Unit.h:1335
#define MAX_GAMEOBJECT_SLOT
Definition: Unit.h:1343
@ UNIT_BYTE2_FLAG_UNK1
Definition: Unit.h:246
@ UNIT_BYTE2_FLAG_SANCTUARY
Definition: Unit.h:248
UnitState
Definition: Unit.h:483
@ UNIT_STATE_EVADE
Definition: Unit.h:505
@ UNIT_STATE_DIED
Definition: Unit.h:484
@ UNIT_STATE_ATTACK_PLAYER
Definition: Unit.h:498
@ UNIT_STATE_POSSESSED
Definition: Unit.h:500
@ UNIT_STATE_UNATTACKABLE
Definition: Unit.h:521
@ UNIT_STATE_CANNOT_AUTOATTACK
Definition: Unit.h:527
@ UNIT_STATE_CONFUSED
Definition: Unit.h:495
@ UNIT_STATE_ROOT
Definition: Unit.h:494
@ UNIT_STATE_CONTROLLED
Definition: Unit.h:524
@ UNIT_STATE_FLEEING
Definition: Unit.h:491
@ UNIT_STATE_NO_ENVIRONMENT_UPD
Definition: Unit.h:512
@ UNIT_STATE_CANNOT_TURN
Definition: Unit.h:528
@ UNIT_STATE_MOVING
Definition: Unit.h:523
@ UNIT_STATE_MOVE
Definition: Unit.h:503
@ UNIT_STATE_MELEE_ATTACKING
Definition: Unit.h:485
@ UNIT_STATE_CASTING
Definition: Unit.h:499
@ UNIT_STATE_STUNNED
Definition: Unit.h:487
PlayerTotemType
Definition: Unit.h:1346
@ SUMMON_TYPE_TOTEM_EARTH
Definition: Unit.h:1348
@ SUMMON_TYPE_TOTEM_WATER
Definition: Unit.h:1349
@ SUMMON_TYPE_TOTEM_FIRE
Definition: Unit.h:1347
@ SUMMON_TYPE_TOTEM_AIR
Definition: Unit.h:1350
std::vector< SpellImmune > SpellImmuneList
Definition: Unit.h:367
#define BASE_MINDAMAGE
Definition: Unit.h:147
UnitMoveType
Definition: Unit.h:536
@ MOVE_FLIGHT
Definition: Unit.h:543
@ MOVE_SWIM
Definition: Unit.h:540
@ MOVE_TURN_RATE
Definition: Unit.h:542
@ MOVE_FLIGHT_BACK
Definition: Unit.h:544
@ MOVE_SWIM_BACK
Definition: Unit.h:541
@ MOVE_RUN
Definition: Unit.h:538
@ MOVE_PITCH_RATE
Definition: Unit.h:545
@ MOVE_RUN_BACK
Definition: Unit.h:539
@ MOVE_WALK
Definition: Unit.h:537
@ REACT_DEFENSIVE
Definition: Unit.h:1152
@ REACT_PASSIVE
Definition: Unit.h:1151
@ UNIT_FLAG_TAXI_FLIGHT
Definition: Unit.h:626
@ UNIT_FLAG_STUNNED
Definition: Unit.h:624
@ UNIT_FLAG_CANNOT_SWIM
Definition: Unit.h:620
@ UNIT_FLAG_NON_ATTACKABLE
Definition: Unit.h:607
@ UNIT_FLAG_IN_COMBAT
Definition: Unit.h:625
@ UNIT_FLAG_NON_ATTACKABLE_2
Definition: Unit.h:622
@ UNIT_FLAG_IMMUNE_TO_NPC
Definition: Unit.h:615
@ UNIT_FLAG_POSSESSED
Definition: Unit.h:630
@ UNIT_FLAG_PACIFIED
Definition: Unit.h:623
@ UNIT_FLAG_SWIMMING
Definition: Unit.h:621
@ UNIT_FLAG_DISABLE_MOVE
Definition: Unit.h:608
@ UNIT_FLAG_NOT_SELECTABLE
Definition: Unit.h:631
@ UNIT_FLAG_RENAME
Definition: Unit.h:610
@ UNIT_FLAG_IMMUNE_TO_PC
Definition: Unit.h:614
@ UNIT_FLAG_NOT_ATTACKABLE_1
Definition: Unit.h:613
@ UNIT_FLAG_PLAYER_CONTROLLED
Definition: Unit.h:609
@ UNIT_FLAG_SKINNABLE
Definition: Unit.h:632
@ UNIT_FLAG_MOUNT
Definition: Unit.h:633
@ UNIT_FLAG_PET_IN_COMBAT
Definition: Unit.h:617
@ UNIT_FLAG2_IGNORE_REPUTATION
Definition: Unit.h:645
DamageEffectType
Definition: Unit.h:593
@ DIRECT_DAMAGE
Definition: Unit.h:594
@ NODAMAGE
Definition: Unit.h:598
@ DOT
Definition: Unit.h:596
@ SPELL_DIRECT_DAMAGE
Definition: Unit.h:595
@ UPDATETYPE_VALUES
Definition: UpdateData.h:28
@ UPDATEFLAG_LIVING
Definition: UpdateData.h:44
@ UPDATEFLAG_VEHICLE
Definition: UpdateData.h:46
@ UPDATEFLAG_STATIONARY_POSITION
Definition: UpdateData.h:45
uint32 UnitUpdateFieldFlags[PLAYER_END]
@ UF_FLAG_SPECIAL_INFO
@ UF_FLAG_PUBLIC
@ UF_FLAG_OWNER
@ UF_FLAG_PRIVATE
@ UF_FLAG_PARTY_MEMBER
@ UNIT_FIELD_MINDAMAGE
Definition: UpdateFields.h:127
@ PLAYER_RANGED_CRIT_PERCENTAGE
Definition: UpdateFields.h:352
@ UNIT_NPC_FLAGS
Definition: UpdateFields.h:139
@ UNIT_FIELD_PETNUMBER
Definition: UpdateFields.h:132
@ PLAYER_CRIT_PERCENTAGE
Definition: UpdateFields.h:351
@ PLAYER_SPELL_CRIT_PERCENTAGE1
Definition: UpdateFields.h:354
@ UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE
Definition: UpdateFields.h:157
@ UNIT_FIELD_POSSTAT0
Definition: UpdateFields.h:146
@ UNIT_FIELD_RANGEDATTACKTIME
Definition: UpdateFields.h:121
@ UNIT_FIELD_HEALTH
Definition: UpdateFields.h:96
@ UNIT_FIELD_ATTACK_POWER_MODS
Definition: UpdateFields.h:163
@ UNIT_FIELD_SUMMONEDBY
Definition: UpdateFields.h:90
@ PLAYER_OFFHAND_CRIT_PERCENTAGE
Definition: UpdateFields.h:353
@ UNIT_FIELD_MAXDAMAGE
Definition: UpdateFields.h:128
@ UNIT_FIELD_DISPLAYID
Definition: UpdateFields.h:124
@ PLAYER_BLOCK_PERCENTAGE
Definition: UpdateFields.h:346
@ UNIT_FIELD_BYTES_0
Definition: UpdateFields.h:95
@ UNIT_FIELD_LEVEL
Definition: UpdateFields.h:114
@ UNIT_FIELD_FACTIONTEMPLATE
Definition: UpdateFields.h:115
@ UNIT_FIELD_RANGED_ATTACK_POWER
Definition: UpdateFields.h:165
@ UNIT_FIELD_MAXPOWER1
Definition: UpdateFields.h:105
@ UNIT_MOD_CAST_SPEED
Definition: UpdateFields.h:137
@ UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER
Definition: UpdateFields.h:167
@ UNIT_FIELD_POSSTAT4
Definition: UpdateFields.h:150
@ UNIT_FIELD_MAXOFFHANDDAMAGE
Definition: UpdateFields.h:130
@ UNIT_FIELD_SUMMON
Definition: UpdateFields.h:87
@ UNIT_FIELD_NEGSTAT4
Definition: UpdateFields.h:155
@ PLAYER_FLAGS
Definition: UpdateFields.h:178
@ UNIT_FIELD_FLAGS_2
Definition: UpdateFields.h:118
@ UNIT_FIELD_AURASTATE
Definition: UpdateFields.h:119
@ UNIT_FIELD_MOUNTDISPLAYID
Definition: UpdateFields.h:126
@ UNIT_FIELD_MAXRANGEDDAMAGE
Definition: UpdateFields.h:169
@ UNIT_FIELD_ATTACK_POWER_MULTIPLIER
Definition: UpdateFields.h:164
@ UNIT_FIELD_ATTACK_POWER
Definition: UpdateFields.h:162
@ UNIT_FIELD_POWER1
Definition: UpdateFields.h:97
@ UNIT_FIELD_CHARMEDBY
Definition: UpdateFields.h:89
@ PLAYER_BYTES
Definition: UpdateFields.h:181
@ UNIT_FIELD_CHARM
Definition: UpdateFields.h:86
@ UNIT_FIELD_PET_NAME_TIMESTAMP
Definition: UpdateFields.h:133
@ UNIT_FIELD_MINRANGEDDAMAGE
Definition: UpdateFields.h:168
@ UNIT_FIELD_FLAGS
Definition: UpdateFields.h:117
@ UNIT_NPC_EMOTESTATE
Definition: UpdateFields.h:140
@ UNIT_FIELD_RANGED_ATTACK_POWER_MODS
Definition: UpdateFields.h:166
@ UNIT_FIELD_HOVERHEIGHT
Definition: UpdateFields.h:173
@ PLAYER_SELF_RES_SPELL
Definition: UpdateFields.h:370
@ UNIT_FIELD_NEGSTAT0
Definition: UpdateFields.h:151
@ UNIT_FIELD_MAXHEALTH
Definition: UpdateFields.h:104
@ UNIT_FIELD_BYTES_1
Definition: UpdateFields.h:131
@ UNIT_FIELD_BYTES_2
Definition: UpdateFields.h:161
@ UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE
Definition: UpdateFields.h:158
@ UNIT_FIELD_MINOFFHANDDAMAGE
Definition: UpdateFields.h:129
@ UNIT_CREATED_BY_SPELL
Definition: UpdateFields.h:138
@ UNIT_FIELD_BASEATTACKTIME
Definition: UpdateFields.h:120
@ UNIT_DYNAMIC_FLAGS
Definition: UpdateFields.h:136
@ VEHICLE_SPELL_PARACHUTE
@ VEHICLE_SPELL_SHADE_CONTROL_END
@ VEHICLE_SPELL_GEIST_CONTROL_END
@ VEHICLE_SPELL_RIDE_HARDCODED
@ NPC_EIDOLON_WATCHER
@ NPC_LITHE_STALKER
struct block_ block
static uint pos(unsigned char c)
Definition: base64.c:104
Weapon
Definition: boss_arlokk.cpp:75
T mod(T x, int y)
Definition: chrono.h:822
void SetRemoveMode(AuraRemoveMode mode)
Definition: SpellAuras.h:72
bool IsPositive() const
Definition: SpellAuras.h:68
Unit * GetTarget() const
Definition: SpellAuras.h:61
uint8 GetEffectMask() const
Definition: SpellAuras.h:66
void _HandleEffect(uint8 effIndex, bool apply)
Definition: SpellAuras.cpp:156
Aura * GetBase() const
Definition: SpellAuras.h:62
AuraRemoveMode GetRemoveMode() const
Definition: SpellAuras.h:73
bool HasEffect(uint8 effect) const
Definition: SpellAuras.h:67
Aura * GetBase() const
void ChangeAmount(int32 newAmount, bool mark=true, bool onStackOrReapply=false)
uint32 GetTickNumber() const
AuraType GetAuraType() const
bool CanBeRecalculated() const
Unit * GetCaster() const
int32 GetOldAmount() const
uint32 GetId() const
int32 GetTotalTicks() const
void HandleEffect(AuraApplication *aurApp, uint8 mode, bool apply)
SpellInfo const * GetSpellInfo() const
void SetAmount(int32 amount)
int32 GetMiscValue() const
uint32 GetEffIndex() const
void HandleProcTriggerDamageAuraProc(AuraApplication *aurApp, ProcEventInfo &eventInfo)
void ResetPeriodic(bool resetPeriodicTimer=false)
int32 GetBaseAmount() const
ObjectGuid GetCasterGUID() const
int32 GetAmount() const
virtual void _UnapplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
Definition: SpellAuras.cpp:506
int32 GetMaxDuration() const
Definition: SpellAuras.h:129
void CallScriptEffectAbsorbHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount, bool &defaultPrevented)
void CallScriptDispel(DispelInfo *dispelInfo)
void SetStackAmount(uint8 num)
Definition: SpellAuras.cpp:947
AuraEffect * GetEffect(uint8 effIndex) const
Definition: SpellAuras.h:174
static Aura * TryCreate(SpellInfo const *spellproto, uint8 effMask, WorldObject *owner, Unit *caster, int32 *baseAmount=nullptr, Item *castItem=nullptr, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemGUID=ObjectGuid::Empty)
Definition: SpellAuras.cpp:347
ObjectGuid GetCasterGUID() const
Definition: SpellAuras.h:105
bool HasEffect(uint8 effIndex) const
Definition: SpellAuras.h:172
bool CanStackWith(Aura const *checkAura, bool remove) const
bool IsRemoved() const
Definition: SpellAuras.h:160
bool IsSingleTargetWith(Aura const *aura) const
bool ModCharges(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: SpellAuras.cpp:925
uint32 GetId() const
Definition: SpellAuras.cpp:461
bool IsAppliedOnTarget(ObjectGuid guid) const
Definition: SpellAuras.h:184
int32 GetDuration() const
Definition: SpellAuras.h:133
void UpdateOwner(uint32 diff, WorldObject *owner)
Definition: SpellAuras.cpp:737
void UnregisterSingleTarget()
bool IsDeathPersistent() const
bool HasEffectType(AuraType type) const
bool ModStackAmount(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, bool periodicReset=false)
Definition: SpellAuras.cpp:973
WorldObject * GetOwner() const
Definition: SpellAuras.h:107
ApplicationMap const & GetApplicationMap()
Definition: SpellAuras.h:180
Unit * GetCaster() const
Definition: SpellAuras.cpp:466
SpellInfo const * GetSpellInfo() const
Definition: SpellAuras.h:100
void SetCharges(uint8 charges)
Definition: SpellAuras.cpp:904
bool CallScriptCheckProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
void ApplyForTargets()
Definition: SpellAuras.h:122
void SetNeedClientUpdateForTargets() const
static Aura * TryRefreshStackOrCreate(SpellInfo const *spellproto, uint8 tryEffMask, WorldObject *owner, Unit *caster, int32 *baseAmount=nullptr, Item *castItem=nullptr, ObjectGuid casterGUID=ObjectGuid::Empty, bool *refresh=nullptr, bool periodicReset=false)
Definition: SpellAuras.cpp:321
uint8 GetEffectMask() const
Definition: SpellAuras.h:175
void SetDuration(int32 duration, bool withMods=false)
Definition: SpellAuras.cpp:849
const AuraApplication * GetApplicationOfTarget(ObjectGuid guid) const
Definition: SpellAuras.h:182
Unit * GetUnitOwner() const
Definition: SpellAuras.h:108
void CallScriptEffectAfterAbsorbHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount)
void CallScriptEffectManaShieldHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount, bool &defaultPrevented)
AuraObjectType GetType() const
Definition: SpellAuras.cpp:476
uint8 GetStackAmount() const
Definition: SpellAuras.h:147
uint8 GetCharges() const
Definition: SpellAuras.h:140
ObjectGuid GetCastItemGUID() const
Definition: SpellAuras.h:103
void SetMaxDuration(int32 duration)
Definition: SpellAuras.h:130
void HandleAuraSpecificMods(AuraApplication const *aurApp, Unit *caster, bool apply, bool onReapply)
void SetIsSingleTarget(bool val)
Definition: SpellAuras.h:165
virtual void _ApplyForTarget(Unit *target, Unit *caster, AuraApplication *auraApp)
Definition: SpellAuras.cpp:487
bool IsPassive() const
time_t GetApplyTime() const
Definition: SpellAuras.h:128
void CallScriptEffectAfterManaShieldHandlers(AuraEffect *aurEff, AuraApplication const *aurApp, DamageInfo &dmgInfo, uint32 &absorbAmount)
bool IsPermanent() const
Definition: SpellAuras.h:138
std::map< ObjectGuid, AuraApplication * > ApplicationMap
Definition: SpellAuras.h:90
virtual void Remove(AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)=0
void CallScriptAfterDispel(DispelInfo *dispelInfo)
void _Remove(AuraRemoveMode removeMode)
Definition: SpellAuras.cpp:541
bool IsSingleTarget() const
Definition: SpellAuras.h:163
ObjectGuid _targetGUID
Definition: Unit.cpp:19310
AuraMunchingQueue(Unit &owner, ObjectGuid targetGUID, int32 basePoints, uint32 spellId)
Definition: Unit.cpp:19297
bool Execute(uint64, uint32) override
Definition: Unit.cpp:19299
static size_t BuildChatPacket(WorldPacket &data, ChatMsg chatType, Language language, ObjectGuid senderGUID, ObjectGuid receiverGUID, std::string_view message, uint8 chatTag, std::string const &senderName="", std::string const &receiverName="", uint32 achievementId=0, bool gmMessage=false, std::string const &channelName="")
Definition: Chat.cpp:197
bool Execute(uint64 e_time, uint32 p_time) override
Definition: Unit.cpp:19503
virtual void OwnerAttackedBy(Unit *)
Definition: CreatureAI.h:146
void OnCharmed(bool apply) override
Definition: CreatureAI.cpp:45
virtual void AttackedBy(Unit *)
Definition: CreatureAI.h:126
virtual void OnSpellClick(Unit *, bool &)
Definition: CreatureAI.h:174
virtual void JustDied(Unit *)
Definition: CreatureAI.h:106
virtual void MovementInform(uint32, uint32)
Definition: CreatureAI.h:133
virtual void KilledUnit(Unit *)
Definition: CreatureAI.h:109
virtual void EnterEvadeMode()
Definition: CreatureAI.cpp:197
float GetSpellDamageMod(int32 Rank)
Definition: Creature.cpp:1447
Loot loot
Definition: Creature.h:211
bool IsTrigger() const
Definition: Creature.h:75
bool _CanDetectFeignDeathOf(const Unit *target) const
Definition: Creature.cpp:2343
void CallAssistance(Unit *target=nullptr)
Definition: Creature.cpp:2204
bool IsDungeonBoss() const
Definition: Creature.cpp:2862
bool isWorldBoss() const
Definition: Creature.h:109
uint16 GetLootMode() const
Definition: Creature.h:225
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition: Creature.h:235
void SetLootRecipient(Unit *unit, bool withGroup=true)
Definition: Creature.cpp:1161
bool CanCreatureAttack(Unit const *victim, bool skipDistCheck=false) const
Definition: Creature.cpp:2387
void SetLastDamagedTime(time_t val)
Definition: Creature.cpp:3427
bool IsEvadingAttacks() const
Definition: Creature.h:124
bool HasReactState(ReactStates state) const
Definition: Creature.h:85
bool IsValidTrainerForPlayer(Player *player, uint32 *npcFlags=nullptr) const
Definition: Creature.cpp:1106
void SetReactState(ReactStates st)
Definition: Creature.h:83
bool HasMechanicTemplateImmunity(uint32 mask) const
Definition: Creature.cpp:1993
bool hasLootRecipient() const
Definition: Creature.h:216
void SetPosition(float x, float y, float z, float o)
Definition: Creature.cpp:2854
Player * GetLootRecipient() const
Definition: Creature.cpp:1147
bool IsDamageEnoughForLootingAndReward() const
Definition: Creature.h:341
bool isTappedBy(Player const *player) const
Definition: Creature.cpp:1222
void UpdateMovementFlags()
Definition: Creature.cpp:3164
Unit * SelectVictim()
Definition: Unit.cpp:13900
void DespawnOrUnsummon(Milliseconds msTimeToDespawn, Seconds forcedRespawnTimer)
Definition: Creature.cpp:1945
Group * GetLootRecipientGroup() const
Definition: Creature.cpp:1154
ReactStates GetReactState() const
Definition: Creature.h:84
CreatureAI * AI() const
Definition: Creature.h:129
void UpdateMoveInLineOfSightState()
Definition: Creature.cpp:2350
CreatureTemplate const * GetCreatureTemplate() const
Definition: Creature.h:190
void SetAssistanceTimer(uint32 value)
Definition: Creature.h:383
void SendAIReaction(AiReaction reactionType)
Definition: Creature.cpp:2192
bool IsInEvadeMode() const
Definition: Creature.h:123
void LowerPlayerDamageReq(uint32 unDamage)
Definition: Creature.h:342
void AddSpellMod(SpellValueMod mod, int32 value)
Definition: Unit.h:136
void ResistDamage(uint32 amount)
Definition: Unit.cpp:151
void AbsorbDamage(uint32 amount)
Definition: Unit.cpp:144
uint32 m_resist
Definition: Unit.h:913
void ModifyDamage(int32 amount)
Definition: Unit.cpp:138
SpellInfo const * GetSpellInfo() const
Definition: Unit.h:928
uint32 GetUnmitigatedDamage() const
Definition: Unit.cpp:165
DamageInfo(Unit *_attacker, Unit *_victim, uint32 _damage, SpellInfo const *_spellInfo, SpellSchoolMask _schoolMask, DamageEffectType _damageType, uint32 cleanDamage=0)
Definition: Unit.cpp:114
uint32 m_block
Definition: Unit.h:914
void BlockDamage(uint32 amount)
Definition: Unit.cpp:158
DamageEffectType GetDamageType() const
Definition: Unit.h:930
uint32 GetResist() const
Definition: Unit.h:934
SpellSchoolMask GetSchoolMask() const
Definition: Unit.h:929
uint32 m_absorb
Definition: Unit.h:912
uint32 m_cleanDamage
Definition: Unit.h:915
uint32 m_damage
Definition: Unit.h:907
Unit * GetAttacker() const
Definition: Unit.h:926
uint32 GetDamage() const
Definition: Unit.h:932
Unit * GetVictim() const
Definition: Unit.h:927
uint32 GetAbsorb() const
Definition: Unit.h:933
uint8 GetRemovedCharges() const
Definition: Unit.h:876
uint32 GetSpellId() const
Definition: DynamicObject.h:58
static float GetReqMoveDistSq(uint32 map_type)
void AddEvent(BasicEvent *Event, uint64 e_time, bool set_addtime=true)
void KillAllEvents(bool force)
uint64 CalculateTime(uint64 t_offset) const
uint64 CalculateQueueTime(uint64 delay) const
void Update(uint32 p_time)
void SetValue(FLAG_TYPE flag, T_VALUES value)
Definition: Object.h:636
float y
Definition: Vector3.h:62
float x
Definition: Vector3.h:62
float z
Definition: Vector3.h:62
uint32 GetSpellId() const
Definition: GameObject.h:802
void Delete()
Definition: GameObject.cpp:889
void SetOwnerGUID(ObjectGuid owner)
Definition: GameObject.h:784
ObjectGuid GetOwnerGUID() const
Definition: GameObject.h:794
void SetRespawnTime(int32 respawn)
bool HasGlobalCooldown(SpellInfo const *spellInfo) const
Definition: Unit.cpp:323
GlobalCooldownList m_GlobalCooldowns
Definition: Unit.h:1136
void AddGlobalCooldown(SpellInfo const *spellInfo, uint32 gcd)
Definition: Unit.cpp:329
void CancelGlobalCooldown(SpellInfo const *spellInfo)
Definition: Unit.cpp:334
Definition: Group.h:167
uint8 GetMemberGroup(ObjectGuid guid) const
Definition: Group.cpp:2235
void BroadcastPacket(WorldPacket *packet, bool ignorePlayersInBGRaid, int group=-1, ObjectGuid ignore=ObjectGuid::Empty)
Definition: Group.cpp:1669
GroupReference * GetFirstMember()
Definition: Group.h:239
uint32 GetMembersCount() const
Definition: Group.h:241
ObjectGuid GetLooterGuid() const
Definition: Group.cpp:2172
LootMethod GetLootMethod() const
Definition: Group.cpp:2167
void UpdateLooterGuid(WorldObject *pLootedObject, bool ifneed=false)
Definition: Group.cpp:1780
bool isRaidGroup() const
Definition: Group.cpp:2132
void SendLooter(Creature *creature, Player *pLooter)
Definition: Group.cpp:934
GroupReference * next()
bool InitStatsForLevel(uint8 level)
Definition: Pet.cpp:748
Definition: Unit.h:941
SpellInfo const * GetSpellInfo() const
Definition: Unit.h:971
Unit * GetHealer() const
Definition: Unit.h:967
uint32 GetAbsorb() const
Definition: Unit.h:970
void SetHeal(uint32 amount)
Definition: Unit.h:962
Unit * GetTarget() const
Definition: Unit.h:968
void AbsorbHeal(uint32 amount)
Definition: Unit.h:955
uint32 GetHeal() const
Definition: Unit.h:969
void deleteReferences(bool removeFromMap=false)
void setOnlineOfflineState(bool isOnline)
void threatAssist(Unit *victim, float baseThreat, SpellInfo const *threatSpell=nullptr)
HostileReference * getFirst()
Definition: HostileRefMgr.h:60
void deleteReferencesForFaction(uint32 faction)
ObjectGuid getUnitGuid() const
Definition: ThreatMgr.h:98
HostileReference * next()
Definition: ThreatMgr.h:107
void PermBindAllPlayers()
Definition: Map.cpp:3091
Definition: Item.h:214
uint8 GetSlot() const
Definition: Item.h:272
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition: Item.h:295
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:507
bool IsBroken() const
Definition: Item.h:251
bool IsEquipped() const
Definition: Item.cpp:752
uint32 GetSkill()
Definition: Item.cpp:518
bool isEmpty() const
Definition: LinkedList.h:97
Definition: Map.h:299
bool IsDungeon() const
Definition: Map.h:434
void PlayerRelocation(Player *, float x, float y, float z, float o)
Definition: Map.cpp:992
uint8 GetSpawnMode() const
Definition: Map.h:406
std::unordered_set< Unit * > i_objectsForDelayedVisibility
Definition: Map.h:375
InstanceMap * ToInstanceMap()
Definition: Map.h:529
void CreatureRelocation(Creature *creature, float x, float y, float z, float o)
Definition: Map.cpp:1014
bool IsRaidOrHeroicDungeon() const
Definition: Map.h:437
bool IsBattleArena() const
Definition: Map.h:441
Unit * GetOwner() const
bool IsGuardianPet() const
void setDeathState(DeathState s, bool despawn=false) override
bool IsPetGhoul() const
void UpdateMotion(uint32 diff)
void InitDefault()
void MoveChase(Unit *target, std::optional< ChaseRange > dist={}, std::optional< ChaseAngle > angle={})
MovementGeneratorType GetCurrentMovementGeneratorType() const
void ReinitializeMovement()
void MovementExpiredOnSlot(MovementSlot slot, bool reset=true)
Definition: MotionMaster.h:192
void MoveFollow(Unit *target, float dist, float angle, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
void MoveConfused()
void MovementExpired(bool reset=true)
Definition: MotionMaster.h:178
void MovePoint(uint32 id, const Position &pos, bool generatePath=true, bool forceDestination=true)
Definition: MotionMaster.h:210
void MoveJump(Position const &pos, float speedXY, float speedZ, uint32 id=0)
Definition: MotionMaster.h:224
uint32 GetCurrentSplineId() const
void MoveJumpTo(float angle, float speedXY, float speedZ)
void MoveFall(uint32 id=0, bool addFlagForNPC=false)
void Clear(bool reset=true)
Definition: MotionMaster.h:165
void MoveFleeing(Unit *enemy, uint32 time=0)
Location ComputePosition() const
Definition: MoveSpline.cpp:26
uint32 GetId() const
Definition: MoveSpline.h:115
bool isFalling() const
Definition: MoveSpline.h:118
bool Finalized() const
Definition: MoveSpline.h:116
Vector3 FinalDestination() const
Definition: MoveSpline.h:120
int32 currentPathIdx() const
Definition: MoveSpline.cpp:315
uint8 GetAnimationType() const
Definition: MoveSpline.h:125
bool Initialized() const
Definition: MoveSpline.h:93
void updateState(int32 difftime, UpdateHandler &handler)
Definition: MoveSpline.h:98
bool HasAnimation() const
Definition: MoveSpline.h:124
bool HasStarted() const
Definition: MoveSpline.h:129
void DisableTransportPathTransformations()
void MoveTo(const Vector3 &destination, bool generatePath=false, bool forceDestination=false)
void SetVelocity(float velocity)
void SetFacing(float angle)
PackedGuid WriteAsPacked() const
Definition: ObjectGuid.h:318
static ObjectGuid const Empty
Definition: ObjectGuid.h:122
bool IsPlayer() const
Definition: ObjectGuid.h:170
std::string ToString() const
Definition: ObjectGuid.cpp:47
void Clear()
Definition: ObjectGuid.h:140
void ApplyModSignedFloatValue(uint16 index, float val, bool apply)
Definition: Object.cpp:813
uint8 GetByteValue(uint16 index, uint8 offset) const
Definition: Object.cpp:318
void SetByteValue(uint16 index, uint8 offset, uint8 value)
Definition: Object.cpp:741
uint16 m_objectType
Definition: Object.h:212
int32 GetInt32Value(uint16 index) const
Definition: Object.cpp:294
bool IsPlayer() const
Definition: Object.h:180
float GetObjectScale() const
Definition: Object.h:104
uint32 GetUInt32Value(uint16 index) const
Definition: Object.cpp:300
bool IsInWorld() const
Definition: Object.h:93
Creature * ToCreature()
Definition: Object.h:183
uint16 _fieldNotifyFlags
Definition: Object.h:228
bool AddGuidValue(uint16 index, ObjectGuid value)
Definition: Object.cpp:677
void RemoveFieldNotifyFlag(uint16 flag)
Definition: Object.h:175
UpdateMask _changesMask
Definition: Object.h:224
TypeID GetTypeId() const
Definition: Object.h:107
uint32 * m_uint32Values
Definition: Object.h:220
uint16 m_valuesCount
Definition: Object.h:226
void SetFlag(uint16 index, uint32 newFlag)
Definition: Object.cpp:836
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition: Object.cpp:851
float GetFloatValue(uint16 index) const
Definition: Object.cpp:312
void SetGuidValue(uint16 index, ObjectGuid value)
Definition: Object.cpp:714
uint32 GetEntry() const
Definition: Object.h:101
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition: Object.cpp:252
bool RemoveGuidValue(uint16 index, ObjectGuid value)
Definition: Object.cpp:695
Unit * ToUnit()
Definition: Object.h:186
bool HasFlag(uint16 index, uint32 flag) const
Definition: Object.cpp:880
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:98
PackedGuid const & GetPackGUID() const
Definition: Object.h:100
float * m_floatValues
Definition: Object.h:221
bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
Definition: Object.cpp:940
void SetFieldNotifyFlag(uint16 flag)
Definition: Object.h:174
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:641
uint16 m_updateFlag
Definition: Object.h:215
Player * ToPlayer()
Definition: Object.h:181
ObjectGuid GetGUID() const
Definition: Object.h:99
TypeID m_objectTypeId
Definition: Object.h:214
void ApplyPercentModFloatValue(uint16 index, float val, bool apply)
Definition: Object.cpp:820
void SetStatInt32Value(uint16 index, int32 value)
Definition: Object.cpp:789
Definition: PetAI.h:47
int32 GetDamage() const
Definition: SpellMgr.h:491
uint32 GetAura(uint32 petEntry) const
Definition: SpellMgr.h:470
Definition: Pet.h:55
bool CreateBaseAtCreatureInfo(CreatureTemplate const *cinfo, Unit *owner)
Definition: Pet.cpp:706
bool CreateBaseAtCreature(Creature *creature)
Definition: Pet.cpp:671
bool isControlled() const
Definition: Pet.h:67
void InitPetCreateSpells()
Definition: Pet.cpp:1735
void SetAuraUpdateMaskForRaid(uint8 slot)
Definition: Pet.h:159
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, Unit *unit=nullptr)
ReputationMgr & GetReputationMgr()
Definition: Player.h:2067
static TeamId TeamIdForRace(uint8 race)
Definition: Player.cpp:5634
void SetSpellModTakingSpell(Spell *spell, bool apply)
Definition: Player.cpp:9375
bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const
Definition: Player.cpp:12668
bool NeedSendSpectatorData() const
Definition: Player.cpp:14524
void SendAttackSwingCancelAttack()
Definition: PlayerMisc.cpp:138
bool IsInSameRaidWith(Player const *p) const
Definition: Player.h:1825
PlayerSpellMap const & GetSpellMap() const
Definition: Player.h:1705
bool HasItemFitToSpellRequirements(SpellInfo const *spellInfo, Item const *ignoreItem=nullptr) const
Definition: Player.cpp:11713
WorldSession * GetSession() const
Definition: Player.h:1940
void SendRemoveControlBar()
Definition: Player.cpp:9128
void SetGroupUpdateFlag(uint32 flag)
Definition: Player.h:2437
void DuelComplete(DuelCompleteType type)
Definition: Player.cpp:6230
void RestoreSpellMods(Spell *spell, uint32 ownerAuraId=0, Aura *aura=nullptr)
Definition: Player.cpp:9235
uint16 GetSkillValue(uint32 skill) const
Definition: Player.cpp:5287
void CastItemCombatSpell(Unit *target, WeaponAttackType attType, uint32 procVictim, uint32 procEx)
Definition: Player.cpp:6967
void SendAutoRepeatCancel(Unit *target)
Definition: PlayerMisc.cpp:150
void UpdatePvP(bool state, bool _override=false)
SafeUnitPointer m_mover
Definition: Player.h:2298
uint8 m_forced_speed_changes[MAX_MOVE_TYPE]
Definition: Player.h:2365
float GetRatingBonusValue(CombatRating cr) const
Definition: Player.cpp:5033
void SendDirectMessage(WorldPacket *data)
Definition: Player.cpp:5529
void CharmSpellInitialize()
Definition: Player.cpp:9074
void UpdateCombatSkills(Unit *victim, WeaponAttackType attType, bool defence, Item *item=nullptr)
void ClearComboPoints()
Definition: Player.cpp:10832
Group * GetGroup()
Definition: Player.h:2431
uint32 GetBaseSpellPowerBonus()
Definition: Player.h:1913
bool HaveAtClient(WorldObject const *u) const
Definition: Player.h:2349
bool InBattleground() const
Definition: Player.h:2190
void DurabilityPointLossForEquipSlot(EquipmentSlots slot)
Definition: Player.cpp:4652
TeamId GetTeamId(bool original=false) const
Definition: Player.h:2050
bool SetCanFly(bool apply, bool packetOnly=false) override
Definition: Player.cpp:14983
void PetSpellInitialize()
Definition: Player.cpp:8899
Item * GetUseableItemByPos(uint8 bag, uint8 slot) const
Definition: Player.h:1190
void SetFallInformation(uint32 time, float z)
Definition: Player.h:2301
uint8 GetComboPoints() const
Definition: Player.h:1572
void UpdatePvPState()
Pet * GetPet() const
Definition: Player.cpp:8649
Battleground * GetBattleground(bool create=false) const
Definition: Player.cpp:11489
uint32 GetResurrectionSpellId()
Definition: Player.cpp:11807
bool GetCommandStatus(uint32 command) const
Definition: Player.h:1132
OutdoorPvP * GetOutdoorPvP() const
Definition: Player.cpp:11708
bool HasSpellCooldown(uint32 spell_id) const override
Definition: Player.h:1721
int32 GetSpellPenetrationItemMod() const
Definition: Player.h:1914
uint16 GetMaxSkillValue(uint32 skill) const
Definition: Player.cpp:5304
void RewardPlayerAndGroupAtKill(Unit *victim, bool isBattleGround)
Definition: Player.cpp:11924
void AddSpellAndCategoryCooldowns(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=nullptr, bool infinityCooldown=false)
Definition: Player.cpp:10176
void StopCastingCharm()
Definition: Player.cpp:8747
void AddComboPoints(Unit *target, int8 count)
Definition: Player.cpp:10800
void RemoveCategoryCooldown(uint32 cat)
Definition: Player.cpp:3422
void AddSpellCooldown(uint32 spell_id, uint32 itemid, uint32 end_time, bool needSendToClient=false, bool forceSendToSpectator=false) override
Definition: Player.cpp:10349
bool IsGameMaster() const
Definition: Player.h:1114
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0, Unit *target=nullptr, bool newInstance=false)
Definition: Player.cpp:1300
SpellCooldowns GetSpellCooldowns() const
Definition: Player.h:2110
static uint8 GetAttackBySlot(uint8 slot)
void ToggleAFK()
Definition: Player.cpp:1261
void PossessSpellInitialize()
Definition: Player.cpp:8971
void StopCastingBindSight()
Definition: Player.cpp:12346
void SendMessageToSet(WorldPacket *data, bool self) override
Definition: Player.h:1968
void SetClientControl(Unit *target, bool allowMove, bool packetOnly=false)
Definition: Player.cpp:12050
ReputationRank GetReputationRank(uint32 faction_id) const
Definition: Player.cpp:5666
bool IsSpectator() const
Definition: Player.h:2529
Unit * GetSelectedUnit() const
Definition: Player.cpp:10757
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
bool isHonorOrXPTarget(Unit *victim) const
Definition: Player.cpp:11864
float GetRealDodge() const
Definition: Player.h:2564
uint8 GetSubGroup() const
Definition: Player.h:2435
bool isAFK() const
Definition: Player.h:1093
void VehicleSpellInitialize()
Definition: Player.cpp:8999
void RemoveSpellCooldown(uint32 spell_id, bool update=false)
Definition: Player.cpp:3414
void Say(std::string_view text, Language language, WorldObject const *=nullptr) override
Handles said message in regular chat based on declared language and in config pre-defined Range.
Definition: Player.cpp:8776
void SetFactionForRace(uint8 race)
Definition: Player.cpp:5653
bool isAllowedToLoot(const Creature *creature)
Item * GetItemByGuid(ObjectGuid guid) const
void ResummonPetTemporaryUnSummonedIfAny()
Definition: Player.cpp:13386
ObjectGuid GetComboTarget() const
Definition: Player.h:1573
bool CanSeeSpellClickOn(Creature const *creature) const
Definition: Player.cpp:13423
void SetContestedPvPTimer(uint32 newTime)
Definition: Player.h:1808
Spell * m_spellModTakingSpell
Definition: Player.h:2505
uint32 GetDelayedOperations() const
Definition: Player.h:2040
void SendCooldownEvent(SpellInfo const *spellInfo, uint32 itemId=0, Spell *spell=nullptr, bool setCooldown=true)
Definition: Player.cpp:10369
DuelInfo * duel
Definition: Player.h:1817
bool IsInSameGroupWith(Player const *p) const
Definition: Player.cpp:2245
std::set< Unit * > m_isInSharedVisionOf
Definition: Player.h:2300
DamageInfo * _damageInfo
Definition: Unit.h:987
void SetProcCooldown(uint32 cooldown)
Definition: Unit.h:1009
SpellInfo const * GetTriggerAuraSpell() const
Definition: Unit.h:1006
HealInfo * _healInfo
Definition: Unit.h:988
Spell const * _spell
Definition: Unit.h:986
ProcEventInfo(Unit *actor, Unit *actionTarget, Unit *procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell const *spell, DamageInfo *damageInfo, HealInfo *healInfo, SpellInfo const *triggeredByAuraSpell=nullptr, int8 procAuraEffectIndex=-1)
Definition: Unit.cpp:170
SpellInfo const * GetSpellInfo() const
Definition: Unit.cpp:176
Unit * GetActor()
Definition: Unit.h:994
Unit * GetActionTarget() const
Definition: Unit.h:995
Unit * GetProcTarget() const
Definition: Unit.h:996
AuraEffect * _auraEffect
Definition: Unit.h:2734
ObjectGuid _auraOwnerGUID
Definition: Unit.h:2733
bool Execute(uint64 e_time, uint32 p_time) override
Definition: Unit.cpp:10376
Unit & _self
Definition: Unit.h:2732
FROM * GetSource() const
Definition: Reference.h:97
FactionState const * GetState(FactionEntry const *factionEntry) const
Definition: ReputationMgr.h:73
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
Definition: ReputationMgr.h:98
bool IsAtWar(uint32 faction_id) const
Unit * defaultValue
Definition: Unit.h:1415
void SetPointedTo(Unit *u)
Definition: Unit.cpp:3829
void UnitDeleted()
Definition: Unit.cpp:3836
Unit * ptr
Definition: Unit.h:1414
void SetDst(float x, float y, float z, float orientation, uint32 mapId=MAPID_INVALID)
Definition: Spell.cpp:408
void SetGOTarget(GameObject *target)
Definition: Spell.cpp:273
void SetUnitTarget(Unit *target)
Definition: Spell.cpp:241
Definition: Spell.h:284
void cast(bool skipCheck=false)
Definition: Spell.cpp:3540
SpellCastResult prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=nullptr)
Definition: Spell.cpp:3243
void SetSpellValue(SpellValueMod mod, int32 value)
Definition: Spell.cpp:7921
bool IsInterruptable() const
Definition: Spell.h:546
void SetExecutedCurrently(bool yes)
Definition: Spell.h:547
void SendChannelUpdate(uint32 time)
Definition: Spell.cpp:4780
void SendInterrupted(uint8 result)
Definition: Spell.cpp:4763
SpellInfo const * m_spellInfo
Definition: Spell.h:520
int32 GetCastTime() const
Definition: Spell.h:534
uint32 getState() const
Definition: Spell.h:482
void cancel(bool bySelf=false)
Definition: Spell.cpp:3475
Item * m_weaponItem
Definition: Spell.h:522
CurrentSpellTypes GetCurrentContainer() const
Definition: Spell.cpp:7392
SpellCastResult CheckCast(bool strict)
Definition: Spell.cpp:5237
SpellInfo const * GetSpellInfo() const
Definition: Spell.h:561
static void SendCastResult(Player *caster, SpellInfo const *spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError=SPELL_CUSTOM_ERROR_NONE)
Definition: Spell.cpp:4310
Spell ** m_selfContainer
Definition: Spell.h:593
void SetReferencedFromCurrent(bool yes)
Definition: Spell.h:545
Item * m_CastItem
Definition: Spell.h:521
void finish(bool ok=true)
Definition: Spell.cpp:4100
uint32 MaxLevel
Definition: SpellInfo.h:353
uint32 SpellLevel
Definition: SpellInfo.h:355
bool IsRankOf(SpellInfo const *spellInfo) const
Definition: SpellInfo.cpp:2510
uint32 GetMaxTicks() const
Definition: SpellInfo.cpp:2310
uint32 GetEffectMechanicMask(uint8 effIndex) const
Definition: SpellInfo.cpp:1947
SpellInfo const * GetFirstRankSpell() const
Definition: SpellInfo.cpp:2442
bool IsAutocastable() const
Definition: SpellInfo.cpp:1086
uint32 GetCategory() const
Definition: SpellInfo.cpp:863
bool IsRequiringDeadTarget() const
Definition: SpellInfo.cpp:1205
uint32 ManaCostPerlevel
Definition: SpellInfo.h:359
flag96 SpellFamilyFlags
Definition: SpellInfo.h:382
bool ValidateAttribute6SpellDamageMods(const Unit *caster, const AuraEffect *auraEffect, bool isDot) const
Definition: SpellInfo.cpp:1711
bool IsDeathPersistent() const
Definition: SpellInfo.cpp:1200
bool IsCooldownStartedOnEvent() const
Definition: SpellInfo.cpp:1195
bool IsPassive() const
Definition: SpellInfo.cpp:1081
uint32 Mechanic
Definition: SpellInfo.h:318
uint32 Id
Definition: SpellInfo.h:315
uint8 GetRank() const
Definition: SpellInfo.cpp:2435
SpellRangeEntry const * RangeEntry
Definition: SpellInfo.h:364
uint32 PowerType
Definition: SpellInfo.h:357
uint32 GetDispelMask() const
Definition: SpellInfo.cpp:1985
SpellSpecificType GetSpellSpecific() const
Definition: SpellInfo.cpp:2079
uint32 Dispel
Definition: SpellInfo.h:317
float Speed
Definition: SpellInfo.h:365
bool IsMultiSlotAura() const
Definition: SpellInfo.cpp:1190
float GetMinRange(bool positive=false) const
Definition: SpellInfo.cpp:2256
int32 GetMaxDuration() const
Definition: SpellInfo.cpp:2287
int32 EquippedItemClass
Definition: SpellInfo.h:370
uint32 SchoolMask
Definition: SpellInfo.h:386
std::array< uint32, 2 > SpellVisual
Definition: SpellInfo.h:374
bool CanPierceImmuneAura(SpellInfo const *aura) const
Definition: SpellInfo.cpp:1295
uint32 ProcFlags
Definition: SpellInfo.h:350
uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
Definition: SpellInfo.cpp:1957
bool IsAllowingDeadTarget() const
Definition: SpellInfo.cpp:1210
Mechanics GetEffectMechanic(uint8 effIndex) const
Definition: SpellInfo.cpp:1968
SpellSchoolMask GetSchoolMask() const
Definition: SpellInfo.cpp:1931
AuraStateType GetAuraState() const
Definition: SpellInfo.cpp:2004
bool IsChanneled() const
Definition: SpellInfo.cpp:1239
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:408
uint32 Attributes
Definition: SpellInfo.h:319
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > Effects
Definition: SpellInfo.h:387
int32 GetDuration() const
Definition: SpellInfo.cpp:2280
uint32 ManaCostPercentage
Definition: SpellInfo.h:362
int32 EquippedItemSubClassMask
Definition: SpellInfo.h:371
float GetMaxRange(bool positive=false, Unit *caster=nullptr, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2265
bool IsCritCapable() const
Definition: SpellInfo.cpp:1160
uint32 GetAllEffectsMechanicMask() const
Definition: SpellInfo.cpp:1936
uint32 SpellIconID
Definition: SpellInfo.h:375
bool NeedsExplicitUnitTarget() const
Definition: SpellInfo.cpp:1016
SpellCastResult CheckTarget(Unit const *caster, WorldObject const *target, bool implicit=true) const
Definition: SpellInfo.cpp:1733
int32 CalcPowerCost(Unit const *caster, SpellSchoolMask schoolMask, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2342
uint32 CalcCastTime(Unit *caster=nullptr, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:2294
bool HasEffect(SpellEffects effect) const
Definition: SpellInfo.cpp:868
bool IsAffectingArea() const
Definition: SpellInfo.cpp:999
bool IsPositive() const
Definition: SpellInfo.cpp:1220
uint32 ProcChance
Definition: SpellInfo.h:351
uint32 DmgClass
Definition: SpellInfo.h:383
uint32 AttributesEx5
Definition: SpellInfo.h:324
bool IsRangedWeaponSpell() const
Definition: SpellInfo.cpp:1259
bool HasAura(AuraType aura) const
Definition: SpellInfo.cpp:876
uint32 StartRecoveryCategory
Definition: SpellInfo.h:345
uint32 SpellFamilyName
Definition: SpellInfo.h:381
uint32 ManaCost
Definition: SpellInfo.h:358
uint32 AuraInterruptFlags
Definition: SpellInfo.h:348
bool IsPositiveEffect(uint8 effIndex) const
Definition: SpellInfo.cpp:1225
bool IsSingleTarget() const
Definition: SpellInfo.cpp:1346
SpellCastResult CheckExplicitTarget(Unit const *caster, WorldObject const *target, Item const *itemTarget=nullptr) const
Definition: SpellInfo.cpp:1881
SplineHandler(Unit *unit)
Definition: Unit.cpp:534
bool operator()(Movement::MoveSpline::UpdateResult result)
Definition: Unit.cpp:536
Unit * _unit
Definition: Unit.cpp:549
virtual void UnSummon(uint32 msTime=0)
const SummonPropertiesEntry *const m_Properties
std::list< HostileReference * > StorageType
Definition: ThreatMgr.h:139
Unit * getHostilTarget()
Definition: ThreatMgr.cpp:475
void clearReferences()
Definition: ThreatMgr.cpp:411
void addThreat(Unit *victim, float threat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=nullptr)
Definition: ThreatMgr.cpp:421
ThreatContainer::StorageType const & getThreatList() const
Definition: ThreatMgr.h:254
ThreatContainer::StorageType const & getOfflineThreatList() const
Definition: ThreatMgr.h:255
void modifyThreatPercent(Unit *victim, int32 percent)
Definition: ThreatMgr.cpp:468
Unit * GetOwner() const
Definition: ThreatMgr.h:221
bool isThreatListEmpty() const
Definition: ThreatMgr.h:212
Definition: Util.h:46
size_type size() const
Definition: Util.h:63
StorageType::const_iterator const_iterator
Definition: Util.h:52
const_iterator begin() const
Definition: Util.h:60
uint32 GetSpell(uint8 slot=0) const
Definition: Totem.h:46
virtual void RemovePassenger(WorldObject *passenger, bool withAll=false)=0
virtual void HealReceived(Unit *, uint32 &)
Definition: UnitAI.h:289
virtual void DamageTaken(Unit *, uint32 &, DamageEffectType, SpellSchoolMask)
Definition: UnitAI.h:286
virtual void HealDone(Unit *, uint32 &)
Definition: UnitAI.h:292
virtual void DamageDealt(Unit *, uint32 &, DamageEffectType)
Definition: UnitAI.h:281
virtual void AttackStart(Unit *)
Definition: UnitAI.cpp:28
Definition: Unit.h:1419
bool HasAuraTypeWithAffectMask(AuraType auratype, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:5227
float GetSpellCritChanceReduction() const
Definition: Unit.h:1680
void EnterVehicle(Unit *base, int8 seatId=-1)
Definition: Unit.cpp:18709
int32 ModifyHealth(int32 val)
Definition: Unit.cpp:13270
uint32 m_reactiveTimer[MAX_REACTIVE]
Definition: Unit.h:2592
void ClearUnitState(uint32 f)
Definition: Unit.h:1520
void OutDebugInfo() const
Definition: Unit.cpp:19256
bool HasNegativeAuraWithAttribute(uint32 flag, ObjectGuid guid=ObjectGuid::Empty)
Definition: Unit.cpp:5257
bool IsStopped() const
Definition: Unit.h:2348
bool IsVehicle() const
Definition: Unit.h:1537
void SetMinion(Minion *minion, bool apply)
Definition: Unit.cpp:10074
std::pair< AuraApplicationMap::iterator, AuraApplicationMap::iterator > AuraApplicationMapBoundsNonConst
Definition: Unit.h:1430
bool IsUnderLastManaUseEffect() const
Definition: Unit.cpp:16452
bool _IsValidAssistTarget(Unit const *target, SpellInfo const *bySpell) const
Definition: Unit.cpp:13179
bool IsCharmed() const
Definition: Unit.h:1951
bool m_duringRemoveFromWorld
Definition: Unit.h:2651
virtual void ProcessTerrainStatusUpdate()
Definition: Unit.cpp:3788
void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:4222
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true, bool bySelf=false)
Definition: Unit.cpp:3589
uint32 GetCreatePowers(Powers power) const
Definition: Unit.cpp:14778
bool HandleAuraRaidProcFromChargeWithValue(AuraEffect *triggeredByAura)
Definition: Unit.cpp:16739
void SetVisible(bool x)
Definition: Unit.cpp:13406
virtual bool IsMovementPreventedByCasting() const
Definition: Unit.cpp:3686
bool HealthAbovePct(int32 pct) const
Definition: Unit.h:1565
void DeleteCharmInfo()
Definition: Unit.cpp:14937
void RemoveGameObject(GameObject *gameObj, bool del)
Definition: Unit.cpp:5668
int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask, const AuraEffect *except=nullptr) const
Definition: Unit.cpp:5462
int32 GetMechanicResistChance(const SpellInfo *spell)
Definition: Unit.cpp:2789
static void ApplyResilience(const Unit *victim, float *crit, int32 *damage, bool isCrit, CombatRating type)
Definition: Unit.cpp:18044
Spell * m_currentSpells[CURRENT_MAX_SPELL]
Definition: Unit.h:2564
float GetHealthPct() const
Definition: Unit.h:1567
void ProcDamageAndSpellFor(bool isVictim, Unit *target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const *procSpellInfo, uint32 damage, SpellInfo const *procAura=nullptr, int8 procAuraEffectIndex=-1, Spell const *procSpell=nullptr, DamageInfo *damageInfo=nullptr, HealInfo *healInfo=nullptr)
Definition: Unit.cpp:15426
uint8 getGender() const
Definition: Unit.h:1547
static float GetEffectiveResistChance(Unit const *owner, SpellSchoolMask schoolMask, Unit const *victim, SpellInfo const *spellInfo=nullptr)
Definition: Unit.cpp:1837
DiminishingLevels GetDiminishing(DiminishingGroup group)
Definition: Unit.cpp:14164
uint32 SpellDamageBonusDone(Unit *victim, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, float TotalMod=0.0f, uint32 stack=1)
Definition: Unit.cpp:10988
virtual void setDeathState(DeathState s, bool despawn=false)
Definition: Unit.cpp:13712
void _RemoveNoStackAurasDueToAura(Aura *aura)
Definition: Unit.cpp:4184
void AddPointedBy(SafeUnitPointer *sup)
Definition: Unit.h:2474
Unit * GetCharm() const
Definition: Unit.cpp:10060
void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 TransitTime, SplineFlags sf=SPLINEFLAG_WALK_MODE)
Definition: Unit.cpp:514
AuraList m_removedAuras
Definition: Unit.h:2568
uint32 GetUnitMovementFlags() const
Definition: Unit.h:2355
LiquidTypeEntry const * _lastLiquid
Definition: Unit.h:2603
bool HasAuraTypeWithValue(AuraType auratype, int32 value) const
Definition: Unit.cpp:5236
void RemoveEvadeAuras()
Definition: Unit.cpp:4936
void RemovePetAura(PetAura const *petSpell)
Definition: Unit.cpp:16507
Aura * GetAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition: Unit.cpp:5076
uint32 GetUnitMeleeSkill(Unit const *target=nullptr) const
Definition: Unit.h:1734
void _UpdateAutoRepeatSpell()
Definition: Unit.cpp:3453
ControlSet m_Controlled
Definition: Unit.h:1947
void IncrDiminishing(DiminishingGroup group)
Definition: Unit.cpp:14190
float GetRangedCritChanceReduction() const
Definition: Unit.h:1679
float GetTotalAuraModValue(UnitMods unitMod) const
Definition: Unit.cpp:14460
uint32 m_transform
Definition: Unit.h:2562
void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID)
Definition: Unit.cpp:4710
void SetFacingTo(float ori)
Definition: Unit.cpp:19637
Unit * GetOwner() const
Definition: Unit.cpp:9994
Unit * GetRedirectThreatTarget() const
Definition: Unit.cpp:18597
static uint32 DealDamage(Unit *attacker, Unit *victim, uint32 damage, CleanDamage const *cleanDamage=nullptr, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=nullptr, bool durabilityLoss=true, bool allowGM=false)
Definition: Unit.cpp:773
bool CanHaveThreatList() const
Definition: Unit.cpp:13775
Movement::MoveSpline * movespline
Definition: Unit.h:2509
void RemoveAurasByShapeShift()
Definition: Unit.cpp:4769
uint32 GetCombatTimer() const
Definition: Unit.h:1780
void CombatStop(bool includingCast=false)
Definition: Unit.cpp:9835
void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode=AURA_REMOVE_BY_DEFAULT, uint32 except=0)
Definition: Unit.cpp:4752
float SpellTakenCritChance(Unit const *caster, SpellInfo const *spellProto, SpellSchoolMask schoolMask, float doneChance, WeaponAttackType attackType, bool skipEffectCheck) const
Definition: Unit.cpp:11409
ReputationRank GetReactionTo(Unit const *target) const
Definition: Unit.cpp:9503
uint32 m_CombatTimer
Definition: Unit.h:2635
void NearTeleportTo(float x, float y, float z, float orientation, bool casting=false, bool vehicleTeleport=false, bool withPet=false, bool removeTransport=false)
Definition: Unit.cpp:19042
bool IsCreatedByPlayer() const
Definition: Unit.h:1909
bool IsValidAttackTarget(Unit const *target) const
Definition: Unit.cpp:13053
bool HasVisibleAuraType(AuraType auraType) const
Definition: Unit.cpp:5208
float GetSpeed(UnitMoveType mtype) const
Definition: Unit.cpp:13584
void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply, SpellImmuneBlockType blockType=SPELL_BLOCK_TYPE_ALL)
Definition: Unit.cpp:12604
void _UnregisterDynObject(DynamicObject *dynObj)
Definition: Unit.cpp:5599
bool m_canModifyStats
Definition: Unit.h:2580
Aura * GetAuraOfRankedSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition: Unit.cpp:5094
bool HasNegativeAuraWithInterruptFlag(uint32 flag, ObjectGuid guid=ObjectGuid::Empty)
Definition: Unit.cpp:5245
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:4293
void AddInterruptMask(uint32 mask)
Definition: Unit.h:2250
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask)
Definition: Unit.cpp:12031
void SetFullHealth()
Definition: Unit.h:1574
void SetMinionGUID(ObjectGuid guid)
Definition: Unit.h:1899
void EnergizeBySpell(Unit *victim, uint32 SpellID, uint32 Damage, Powers powertype)
Definition: Unit.cpp:10644
Diminishing m_Diminishing
Definition: Unit.h:2639
virtual bool HasSpellCooldown(uint32) const
Definition: Unit.h:2487
float SpellDoneCritChance(Unit const *, SpellInfo const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType, bool skipEffectCheck) const
Definition: Unit.cpp:11334
void UpdateHeight(float newZ)
Only server-side height update, does not broadcast to client.
Definition: Unit.cpp:19126
bool isBlockCritical()
Definition: Unit.cpp:2782
bool IsPetAura(Aura const *aura)
Definition: Unit.cpp:16534
ComboPointHolderSet m_ComboPointHolders
Definition: Unit.h:2646
void SetConfused(bool apply)
Definition: Unit.cpp:17450
void _UpdateSpells(uint32 time)
Definition: Unit.cpp:3397
void AddToWorld() override
Definition: Unit.cpp:14806
void SetFaction(uint32 faction)
Definition: Unit.cpp:9495
void RestoreFaction()
Definition: Unit.cpp:17812
AttackerSet const & getAttackers() const
Definition: Unit.h:1505
FactionTemplateEntry const * GetFactionTemplateEntry() const
Definition: Unit.cpp:9473
void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode)
Definition: Unit.cpp:4083
float GetTotalAttackPowerValue(WeaponAttackType attType, Unit *pVictim=nullptr) const
Definition: Unit.cpp:14570
bool GetMeleeAttackPoint(Unit *attacker, Position &pos)
Definition: Unit.cpp:2365
virtual void Say(std::string_view text, Language language, WorldObject const *target=nullptr)
Definition: Unit.cpp:20149
bool HasBreakableByDamageCrowdControlAura(Unit *excludeCasterChannel=nullptr) const
Definition: Unit.cpp:750
void DelayOwnedAuras(uint32 spellId, ObjectGuid caster, int32 delaytime)
Definition: Unit.cpp:4957
VisibleAuraMap const * GetVisibleAuras()
Definition: Unit.h:2238
void SetControlled(bool apply, UnitState state)
Definition: Unit.cpp:17189
bool IsImmunedToSchool(SpellSchoolMask meleeSchoolMask) const
Definition: Unit.cpp:12114
SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const
Definition: Unit.cpp:14487
void SetStunned(bool apply)
Definition: Unit.cpp:17288
uint32 GetModelForForm(ShapeshiftForm form) const
Definition: Unit.cpp:18299
Stats GetStatByAuraGroup(UnitMods unitMod) const
Definition: Unit.cpp:14519
uint32 m_state
Definition: Unit.h:2634
float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]
Definition: Unit.h:2578
std::list< Aura * > AuraList
Definition: Unit.h:1436
uint32 GetResistance(SpellSchools school) const
Definition: Unit.h:1554
int32 m_attackTimer[MAX_ATTACK]
Definition: Unit.h:2546
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true, bool bySelf=false)
Definition: Unit.cpp:3656
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
Definition: Unit.cpp:4681
void AddPetAura(PetAura const *petSpell)
Definition: Unit.cpp:16495
float m_modAttackSpeedPct[3]
Definition: Unit.h:2178
uint8 m_realRace
Definition: Unit.h:2541
~Unit() override
Definition: Unit.cpp:341
Player * GetSpellModOwner() const
Definition: Unit.cpp:15937
Spell * FindCurrentSpellBySpellId(uint32 spell_id) const
Definition: Unit.cpp:3671
int32 GetTotalAuraModifierByAffectMask(AuraType auratype, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:5542
DeathState getDeathState()
Definition: Unit.h:1891
Vehicle * m_vehicle
Definition: Unit.h:2599
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo)
Definition: Unit.cpp:5890
Creature * GetVehicleCreatureBase() const
Definition: Unit.cpp:17864
float GetCollisionHeight() const override
Return collision height sent to client.
Definition: Unit.cpp:20116
bool IsTriggeredAtSpellProcEvent(Unit *victim, Aura *aura, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *&spellProcEvent, ProcEventInfo const &eventInfo)
Definition: Unit.cpp:16612
void CombatStartOnCast(Unit *target, bool initialAggro=true, uint32 duration=0)
Definition: Unit.cpp:12893
void RemoveAllGameObjects()
Definition: Unit.cpp:5734
int32 CalculateSpellDamage(Unit const *target, SpellInfo const *spellProto, uint8 effect_index, int32 const *basePoints=nullptr) const
Definition: Unit.cpp:14008
virtual bool IsImmunedToSpell(SpellInfo const *spellInfo)
Definition: Unit.cpp:12153
bool isSpellBlocked(Unit *victim, SpellInfo const *spellProto, WeaponAttackType attackType=BASE_ATTACK)
Definition: Unit.cpp:2756
void SendClearTarget()
Definition: Unit.cpp:19334
uint32 m_rootTimes
Definition: Unit.h:2632
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition: Unit.h:1428
Unit * getAttackerForHelper() const
Definition: Unit.h:1491
float GetSpellMinRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition: Unit.cpp:14315
void _RegisterDynObject(DynamicObject *dynObj)
Definition: Unit.cpp:5594
bool isInFrontInMap(Unit const *target, float distance, float arc=M_PI) const
Definition: Unit.cpp:3719
uint32 MeleeDamageBonusDone(Unit *pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const *spellProto=nullptr)
Definition: Unit.cpp:12288
uint8 m_race
Definition: Unit.h:2542
bool IsPolymorphed() const
Definition: Unit.cpp:16058
bool isFrozen() const
Definition: Unit.cpp:15201
float GetUnitDodgeChance() const
Definition: Unit.cpp:3193
bool HandleDummyAuraProc(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition: Unit.cpp:6013
Vehicle * GetVehicle() const
Definition: Unit.h:2423
float m_weaponDamage[MAX_ATTACK][2]
Definition: Unit.h:2579
ShapeshiftForm GetShapeshiftForm() const
Definition: Unit.h:2153
void ProcDamageAndSpell(Unit *victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType=BASE_ATTACK, SpellInfo const *procSpellInfo=nullptr, SpellInfo const *procAura=nullptr, int8 procAuraEffectIndex=-1, Spell const *procSpell=nullptr, DamageInfo *damageInfo=nullptr, HealInfo *healInfo=nullptr)
Definition: Unit.cpp:5823
Unit * SelectNearbyTarget(Unit *exclude=nullptr, float dist=NOMINAL_MELEE_RANGE) const
Definition: Unit.cpp:16193
float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL)
Definition: Unit.cpp:13802
SpellMissInfo MagicSpellHitResult(Unit *victim, SpellInfo const *spell)
Definition: Unit.cpp:2980
float CalculateDefaultCoefficient(SpellInfo const *spellInfo, DamageEffectType damagetype) const
Definition: Unit.cpp:16405
float GetCombatRatingReduction(CombatRating cr) const
Definition: Unit.cpp:18281
void SendSpellNonMeleeReflectLog(SpellNonMeleeDamage *log, Unit *attacker)
Definition: Unit.cpp:5749
AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraApplication *except=nullptr) const
Definition: Unit.cpp:5057
void AddThreat(Unit *victim, float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=nullptr)
Definition: Unit.cpp:13814
virtual void UpdateAttackPowerAndDamage(bool ranged=false)=0
static void CalcHealAbsorb(HealInfo &healInfo)
Definition: Unit.cpp:2218
virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float &minDamage, float &maxDamage)=0
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition: Unit.cpp:10010
virtual void Yell(std::string_view text, Language language, WorldObject const *target=nullptr)
Definition: Unit.cpp:20154
uint32 GetDiseasesByCaster(ObjectGuid casterGUID, uint8 mode=0)
Definition: Unit.cpp:5297
void HandleProcExtraAttackFor(Unit *victim)
Definition: Unit.cpp:2454
bool HandleAuraProc(Unit *victim, uint32 damage, Aura *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool *handled)
Definition: Unit.cpp:8200
virtual bool HasSpellItemCooldown(uint32, uint32) const
Definition: Unit.h:2488
static uint32 CalcArmorReducedDamage(Unit const *attacker, Unit const *victim, const uint32 damage, SpellInfo const *spellInfo, uint8 attackerLevel=0, WeaponAttackType attackType=MAX_ATTACK)
Definition: Unit.cpp:1752
void SetCantProc(bool apply)
Definition: Unit.h:2390
Unit * GetCharmer() const
Definition: Unit.cpp:10002
void PetSpellFail(const SpellInfo *spellInfo, Unit *target, uint32 result)
Definition: Unit.cpp:19444
Pet * CreateTamedPetFrom(Creature *creatureTarget, uint32 spell_id=0)
Definition: Unit.cpp:16550
bool IsHostileToPlayers() const
Definition: Unit.cpp:9654
float GetCollisionRadius() const override
this method gets the radius of a Unit by DB if any value is defined, otherwise it gets the value by t...
Definition: Unit.cpp:20110
UnitAI * i_AI
Definition: Unit.h:2534
uint32 GetDefenseSkillValue(Unit const *target=nullptr) const
Definition: Unit.cpp:3178
void SetContestedPvP(Player *attackedPlayer=nullptr, bool lookForNearContestedGuards=true)
Definition: Unit.cpp:16457
void SendSpellDamageImmune(Unit *target, uint32 spellId)
Definition: Unit.cpp:5914
void _removeAttacker(Unit *pAttacker)
Definition: Unit.h:1487
void SendAttackStateUpdate(CalcDamageInfo *damageInfo)
Definition: Unit.cpp:5924
void RemoveAppliedAuras(std::function< bool(AuraApplication const *)> const &check)
Definition: Unit.cpp:4381
void CastPetAura(PetAura const *aura)
Definition: Unit.cpp:16519
void RemoveAllAurasExceptType(AuraType type)
Definition: Unit.cpp:4892
CharmInfo * m_charmInfo
Definition: Unit.h:2585
bool IsPvP() const
Definition: Unit.h:1624
DynamicObject * GetDynObject(uint32 spellId)
Definition: Unit.cpp:5604
int32 CalcSpellDuration(SpellInfo const *spellProto)
Definition: Unit.cpp:14013
MotionMaster * i_motionMaster
Definition: Unit.h:2590
virtual bool CanFly() const =0
Pet * ToPet()
Definition: Unit.h:2467
void SetAuraStack(uint32 spellId, Unit *target, uint32 stack)
Definition: Unit.cpp:18019
Unit * GetVehicleBase() const
Definition: Unit.cpp:17859
bool haveOffhandWeapon() const
Definition: Unit.cpp:498
bool IsPet() const
Definition: Unit.h:1534
void _addAttacker(Unit *pAttacker)
Definition: Unit.h:1483
bool _instantCast
Definition: Unit.h:2609
void EnterVehicleUnattackable(Unit *base, int8 seatId=-1)
Definition: Unit.cpp:18720
void Dismount()
Definition: Unit.cpp:12739
void SetCharm(Unit *target, bool apply)
Definition: Unit.cpp:10263
void SendTeleportPacket(Position &pos)
Definition: Unit.cpp:19064
MeleeHitOutcome RollMeleeOutcomeAgainst(const Unit *victim, WeaponAttackType attType) const
Definition: Unit.cpp:2463
float ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit *caster, DiminishingLevels Level, int32 limitduration)
Definition: Unit.cpp:14204
uint8 getLevelForTarget(WorldObject const *) const override
Definition: Unit.h:1540
float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const
Definition: Unit.cpp:5502
bool CanDualWield() const
Definition: Unit.h:1471
void SetModelVisible(bool on)
Definition: Unit.cpp:13416
int32 CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, Unit *caster) const
Definition: Unit.cpp:19494
bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled=false, bool skipAutorepeat=false, bool isAutoshoot=false, bool skipInstant=true) const
Definition: Unit.cpp:3626
void UpdateInterruptMask()
Definition: Unit.cpp:717
void setAttackTimer(WeaponAttackType type, int32 time)
Definition: Unit.h:1466
void StartReactiveTimer(ReactiveType reactive)
Definition: Unit.h:2382
void CleanupsBeforeDelete(bool finalCleanup=true) override
Definition: Unit.cpp:14889
uint32 GetMaxHealth() const
Definition: Unit.h:1560
Aura * AddAura(uint32 spellId, Unit *target)
Definition: Unit.cpp:17980
SpellCastResult CastCustomSpell(Unit *victim, uint32 spellId, int32 const *bp0, int32 const *bp1, int32 const *bp2, bool triggered, Item *castItem=nullptr, AuraEffect const *triggeredByAura=nullptr, ObjectGuid originalCaster=ObjectGuid::Empty)
Definition: Unit.cpp:1144
void TauntApply(Unit *victim)
Definition: Unit.cpp:13834
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition: Unit.cpp:4989
bool isAttackingPlayer() const
Definition: Unit.cpp:9859
ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT]
Definition: Unit.h:2151
float GetTotalStatValue(Stats stat, float additionalValue=0.0f) const
Definition: Unit.cpp:14444
virtual void UpdateResistances(uint32 school)=0
void SetInCombatWith(Unit *enemy, uint32 duration=0)
Definition: Unit.cpp:12796
void SetFacingToObject(WorldObject *object)
Definition: Unit.cpp:19647
void UpdateSplineMovement(uint32 t_diff)
Definition: Unit.cpp:552
bool IsLevitating() const
Definition: Unit.h:2447
uint32 GetSpellCritDamageReduction(uint32 damage) const
Definition: Unit.h:1685
RedirectThreatInfo _redirectThreatInfo
Definition: Unit.h:2648
void ExecuteDelayedUnitRelocationEvent()
Definition: Unit.cpp:19513
float GetMeleeCritChanceReduction() const
Definition: Unit.h:1678
void SendMovementHover(Player *sendTo)
Definition: Unit.cpp:19801
void CombatStart(Unit *target, bool initialAggro=true)
Definition: Unit.cpp:12822
bool IsInSanctuary() const
Definition: Unit.h:1623
uint8 getClass() const
Definition: Unit.h:1545
std::pair< AuraMap::const_iterator, AuraMap::const_iterator > AuraMapBounds
Definition: Unit.h:1425
uint32 GetRangedDamageReduction(uint32 damage) const
Definition: Unit.h:1689
bool HandleOverrideClassScriptAuraProc(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 cooldown)
Definition: Unit.cpp:9300
int32 ModSpellDuration(SpellInfo const *spellProto, Unit const *target, int32 duration, bool positive, uint32 effectMask)
Definition: Unit.cpp:14030
float m_createStats[MAX_STATS]
Definition: Unit.h:2548
void UpdateObjectVisibility(bool forced=true, bool fromUpdate=false) override
Definition: Unit.cpp:18229
bool HasAuraWithMechanic(uint32 mechanicMask) const
Definition: Unit.cpp:5268
float ApplyEffectModifiers(SpellInfo const *spellProto, uint8 effect_index, float value) const
Definition: Unit.cpp:13986
virtual void AddSpellCooldown(uint32, uint32, uint32, bool needSendToClient=false, bool forceSendToSpectator=false)
Definition: Unit.h:2489
bool HandleProcTriggerSpell(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition: Unit.cpp:8377
int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition: Unit.cpp:5437
void RemoveAllAurasRequiringDeadTarget()
Definition: Unit.cpp:4871
void UpdateReactives(uint32 p_time)
Definition: Unit.cpp:16155
bool IsAlive() const
Definition: Unit.h:1888
bool CanApplyResilience() const
Definition: Unit.h:2496
AuraEffect * IsScriptOverriden(SpellInfo const *spell, int32 script) const
Definition: Unit.cpp:5285
float m_modRangedHitChance
Definition: Unit.h:2173
float GetCombatReach() const override
Definition: Unit.h:1473
void ExecuteDelayedUnitAINotifyEvent()
Definition: Unit.cpp:19620
uint8 getRace(bool original=false) const
Definition: Unit.cpp:20028
bool IsOnVehicle(const Unit *vehicle) const
Definition: Unit.h:2424
void ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
Definition: Unit.cpp:14479
DeathState m_deathState
Definition: Unit.h:2553
AuraApplicationMap & GetAppliedAuras()
Definition: Unit.h:2004
void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply)
Definition: Unit.cpp:16263
float GetTotalAuraMultiplierByAffectMask(AuraType auratype, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:5554
uint32 m_unitTypeMask
Definition: Unit.h:2602
void StopMoving()
-------—End of Pet responses methods-------—
Definition: Unit.cpp:15987
std::pair< AuraApplicationMap::const_iterator, AuraApplicationMap::const_iterator > AuraApplicationMapBounds
Definition: Unit.h:1429
int32 HealBySpell(HealInfo &healInfo, bool critical=false)
Definition: Unit.cpp:10619
void AddPlayerToVision(Player *player)
Definition: Unit.cpp:10546
bool HasAuraTypeWithCaster(AuraType auratype, ObjectGuid caster) const
Definition: Unit.cpp:5199
void RewardRage(uint32 damage, uint32 weaponSpeedHitFactor, bool attacker)
Definition: Unit.cpp:19191
GameObject * GetGameObject(uint32 spellId) const
Definition: Unit.cpp:5640
bool IsWithinCombatRange(const Unit *obj, float dist2compare) const
Definition: Unit.cpp:625
float processDummyAuras(float TakenTotalMod) const
Definition: Unit.cpp:11242
void SendPlaySpellVisual(uint32 id)
Definition: Unit.cpp:18028
void _ExitVehicle(Position const *exitPosition=nullptr)
Definition: Unit.cpp:18841
uint32 m_removedAurasCount
Definition: Unit.h:2570
uint32 GetRangedCritDamageReduction(uint32 damage) const
Definition: Unit.h:1684
void RemoveAllAurasOnDeath()
Definition: Unit.cpp:4848
void SetHealth(uint32 val)
Definition: Unit.cpp:14619
void SetInCombatState(bool PvP, Unit *enemy=nullptr, uint32 duration=0)
Definition: Unit.cpp:12920
void RemoveVehicleKit()
Definition: Unit.cpp:17844
bool IsStandState() const
Definition: Unit.cpp:16037
void SetMaxPower(Powers power, uint32 val)
Definition: Unit.cpp:14749
ReputationRank GetFactionReactionTo(FactionTemplateEntry const *factionTemplateEntry, Unit const *target) const
Definition: Unit.cpp:9592
bool HasStealthAura() const
Definition: Unit.h:1787
uint32 GetFaction() const
Definition: Unit.h:1602
void RemoveNotOwnSingleTargetAuras()
Definition: Unit.cpp:4645
bool IsInCombatWith(Unit const *who) const
Definition: Unit.cpp:20048
bool IsPetInCombat() const
Definition: Unit.h:1773
void DisableSpline()
Definition: Unit.cpp:613
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition: Unit.cpp:5187
ThreatMgr m_ThreatMgr
Definition: Unit.h:2595
void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
Definition: Unit.cpp:1346
AuraMap::iterator m_auraUpdateIterator
Definition: Unit.h:2569
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition: Unit.h:2143
Unit * GetMeleeHitRedirectTarget(Unit *victim, SpellInfo const *spellInfo=nullptr)
Definition: Unit.cpp:10434
std::map< uint8, AuraApplication * > VisibleAuraMap
Definition: Unit.h:1441
void RemoveAurasWithAttribute(uint32 flags)
Definition: Unit.cpp:4633
bool m_AutoRepeatFirstCast
Definition: Unit.h:2544
uint16 m_delayed_unit_ai_notify_timer
Definition: Unit.h:2481
void TauntFadeOut(Unit *taunter)
Definition: Unit.cpp:13862
void _DeleteRemovedAuras()
Definition: Unit.cpp:3388
bool HandleAuraRaidProcFromCharge(AuraEffect *triggeredByAura)
Definition: Unit.cpp:16828
int32 ModifyPower(Powers power, int32 val)
Definition: Unit.cpp:13328
Unit * GetNextRandomRaidMemberOrPet(float radius)
Definition: Unit.cpp:10491
static int32 DealHeal(Unit *healer, Unit *victim, uint32 addhealth)
Definition: Unit.cpp:10328
Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const
Definition: Unit.cpp:14548
bool IsNeutralToAll() const
Definition: Unit.cpp:9667
uint32 m_extraAttacks
Definition: Unit.h:1480
void SendMovementWaterWalking(Player *sendTo)
Definition: Unit.cpp:19742
AuraEffect * GetAuraEffectDummy(uint32 spellid) const
Definition: Unit.cpp:5045
void CastStop(uint32 except_spellid=0, bool withInstant=true)
Definition: Unit.cpp:1080
std::pair< AuraStateAurasMap::const_iterator, AuraStateAurasMap::const_iterator > AuraStateAurasMapBounds
Definition: Unit.h:1433
float GetUnitMissChance(WeaponAttackType attType) const
Definition: Unit.cpp:3240
void AddUnitState(uint32 f)
Definition: Unit.h:1518
void ClearComboPointHolders()
Definition: Unit.cpp:16128
void Mount(uint32 mount, uint32 vehicleId=0, uint32 creatureEntry=0)
Definition: Unit.cpp:12680
bool bRequestForcedVisibilityUpdate
Definition: Unit.h:2482
void MonsterMoveWithSpeed(float x, float y, float z, float speed)
Definition: Unit.cpp:506
void SendSpellDamageResist(Unit *target, uint32 spellId)
Definition: Unit.cpp:5904
void SendPetActionFeedback(uint8 msg)
-------—Pet responses methods--------------—
Definition: Unit.cpp:15950
bool isInAccessiblePlaceFor(Creature const *c) const
Definition: Unit.cpp:3729
void DisableRotate(bool apply)
Definition: Unit.cpp:17395
uint32 GetModelForTotem(PlayerTotemType totemType)
Definition: Unit.cpp:18499
uint32 BuildAuraStateUpdateForTarget(Unit *target) const
Definition: Unit.cpp:9930
bool IsDuringRemoveFromWorld() const
Definition: Unit.h:2465
float GetSpellMaxRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition: Unit.cpp:14304
int32 GetMaxPositiveAuraModifier(AuraType auratype)
Definition: Unit.cpp:5411
bool m_ControlledByPlayer
Definition: Unit.h:2431
void SetFeared(bool apply)
Definition: Unit.cpp:17406
Unit * GetCharmerOrOwner() const
Definition: Unit.h:1927
int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
Definition: Unit.cpp:5528
void RemoveAurasDueToItemSpell(uint32 spellId, ObjectGuid castItemGuid)
Definition: Unit.cpp:4596
virtual void UpdateDamagePhysical(WeaponAttackType attType)
Definition: StatSystem.cpp:59
void CalculateMeleeDamage(Unit *victim, uint32 damage, CalcDamageInfo *damageInfo, WeaponAttackType attackType=BASE_ATTACK, const bool sittingVictim=false)
Definition: Unit.cpp:1372
void _ApplyAllAuraStatMods()
Definition: Unit.cpp:4983
HostileRefMgr & getHostileRefMgr()
Definition: Unit.h:2236
void propagateSpeedChange()
-------—End of Pet responses methods-------—
Definition: Unit.h:2378
virtual bool SetHover(bool enable, bool packetOnly=false)
Definition: Unit.cpp:19773
uint32 GetCreatureType() const
Definition: Unit.cpp:14324
bool GetRandomContactPoint(const Unit *target, float &x, float &y, float &z, bool force=false) const
Definition: Unit.cpp:677
void AddGameObject(GameObject *gameObj)
Definition: Unit.cpp:5650
bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
Definition: Unit.cpp:14345
void SetLevel(uint8 lvl, bool showLevelChange=true)
Definition: Unit.cpp:14602
void SetCurrentCastedSpell(Spell *pSpell)
Definition: Unit.cpp:3509
virtual bool SetSwim(bool enable)
Definition: Unit.cpp:19692
uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const *target=nullptr) const
Definition: Unit.cpp:3343
std::unordered_set< Unit * > AttackerSet
Definition: Unit.h:1421
uint32 GetPhaseByAuras() const
Definition: Unit.cpp:18152
Aura * GetOwnedAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, Aura *except=nullptr) const
Definition: Unit.cpp:4277
AuraList & GetSingleCastAuras()
Definition: Unit.h:2048
virtual bool UpdatePosition(float x, float y, float z, float ang, bool teleport=false)
Definition: Unit.cpp:19080
DynObjectList m_dynObj
Definition: Unit.h:2558
int32 GetHealthGain(int32 dVal)
Definition: Unit.cpp:13302
virtual bool SetCanFly(bool enable, bool packetOnly=false)
Definition: Unit.cpp:19711
AuraApplicationList m_interruptableAuras
Definition: Unit.h:2574
bool IsInFlight() const
Definition: Unit.h:1768
uint32 m_last_notify_mstime
Definition: Unit.h:2479
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]
Definition: Unit.h:2223
SpellMissInfo SpellHitResult(Unit *victim, SpellInfo const *spell, bool canReflect=false)
Definition: Unit.cpp:3114
void SendTameFailure(uint8 result)
Definition: Unit.cpp:19057
void ModifyAuraState(AuraStateType flag, bool apply)
Definition: Unit.cpp:9891
Totem * ToTotem()
Definition: Unit.h:2468
bool HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint32 familyFlags) const
Definition: Unit.cpp:728
uint32 GetAuraCount(uint32 spellId) const
Definition: Unit.cpp:5171
bool isInBackInMap(Unit const *target, float distance, float arc=M_PI) const
Definition: Unit.cpp:3724
static uint32 SpellCriticalDamageBonus(Unit const *caster, SpellInfo const *spellProto, uint32 damage, Unit const *victim)
Definition: Unit.cpp:11621
uint32 GetNativeDisplayId() const
Definition: Unit.h:2255
float MeleeSpellMissChance(const Unit *victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
Definition: Unit.cpp:18105
uint32 CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
Definition: Unit.cpp:2666
virtual void UpdateArmor()=0
bool HealthBelowPct(int32 pct) const
Definition: Unit.h:1563
void UpdateCharmAI()
Definition: Unit.cpp:14902
void ClearAllReactives()
Definition: Unit.cpp:16142
void SetRooted(bool apply)
Definition: Unit.cpp:17331
EventProcessor m_Events
Definition: Unit.h:2181
void AddUnitMovementFlag(uint32 f)
Definition: Unit.h:2352
float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const
Definition: Unit.cpp:14430
uint32 _oldFactionId
faction before charm
Definition: Unit.h:2653
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:9680
float GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type) const
Definition: Unit.cpp:14594
uint32 SpellDamageBonusTaken(Unit *caster, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack=1)
Definition: Unit.cpp:11131
AuraEffect * GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const
Definition: Unit.h:2056
SafeUnitPointer m_movedByPlayer
Definition: Unit.h:1968
void UpdateAuraForGroup(uint8 slot)
Definition: Unit.cpp:16378
void ClearInPetCombat()
Definition: Unit.cpp:13026
bool HasAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid caster=ObjectGuid::Empty) const
Definition: Unit.cpp:5157
void JumpTo(float speedXY, float speedZ, bool forward=true)
Definition: Unit.cpp:18602
ObjectGuid GetMinionGUID() const
Definition: Unit.h:1898
bool isPossessed() const
Definition: Unit.h:1952
uint16 GetMaxSkillValueForLevel(Unit const *target=nullptr) const
Definition: Unit.h:1653
void SendRemoveFromThreatListOpcode(HostileReference *pHostileReference)
Definition: Unit.cpp:19182
int32 m_baseSpellCritChance
Definition: Unit.h:2175
bool HasUnitMovementFlag(uint32 f) const
Definition: Unit.h:2354
AuraApplication * _CreateAuraApplication(Aura *aura, uint8 effMask)
Definition: Unit.cpp:3980
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, ObjectGuid casterGUID, Unit *dispeller, uint8 chargesRemoved=1)
Definition: Unit.cpp:4453
int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
Definition: Unit.cpp:5514
uint32 GetMaxPower(Powers power) const
Definition: Unit.h:1581
static void Kill(Unit *killer, Unit *victim, bool durabilityLoss=true, WeaponAttackType attackType=BASE_ATTACK, SpellInfo const *spellProto=nullptr)
Definition: Unit.cpp:16879
virtual void UpdateMaxPower(Powers power)=0
void RemoveOwnedAuras(std::function< bool(Aura const *)> const &check)
Definition: Unit.cpp:4368
void _AddAura(UnitAura *aura, Unit *caster)
Definition: Unit.cpp:3941
AttackerSet m_attackers
Definition: Unit.h:2550
bool IsSummon() const
Definition: Unit.h:1531
virtual bool IsInWater() const
Definition: Unit.cpp:3867
uint32 GetHealth() const
Definition: Unit.h:1559
TransportBase * GetDirectTransport() const
Returns the transport this unit is on directly (if on vehicle and transport, return vehicle)
Definition: Unit.cpp:17884
virtual void TextEmote(std::string_view text, WorldObject const *target=nullptr, bool isBossEmote=false)
Definition: Unit.cpp:20159
uint32 GetCreateHealth() const
Definition: Unit.h:2118
void SendMovementFlagUpdate(bool self=false)
Definition: Unit.cpp:16021
void RemoveDynObject(uint32 spellId)
Definition: Unit.cpp:5617
void DeleteThreatList()
Definition: Unit.cpp:13825
Unit * m_attacking
Definition: Unit.h:2551
void UnsummonAllTotems(bool onDeath=false)
Definition: Unit.cpp:10582
bool HasAuraState(AuraStateType flag, SpellInfo const *spellProto=nullptr, Unit const *Caster=nullptr) const
Definition: Unit.cpp:9941
AuraEffect * GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition: Unit.cpp:5003
virtual bool SetFeatherFall(bool enable, bool packetOnly=false)
Definition: Unit.cpp:19751
void SendPlaySpellImpact(ObjectGuid guid, uint32 id)
Definition: Unit.cpp:18036
SharedVisionList const & GetSharedVisionList()
Definition: Unit.h:1969
float GetTotalAuraMultiplier(AuraType auratype) const
Definition: Unit.cpp:5400
std::multimap< uint32, Aura * > AuraMap
Definition: Unit.h:1424
virtual uint32 GetShieldBlockValue() const =0
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:4436
void SetPower(Powers power, uint32 val)
Definition: Unit.cpp:14707
void SendPetTalk(uint32 pettalk)
Definition: Unit.cpp:15961
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:5194
std::set< SafeUnitPointer * > SafeUnitPointerSet
Definition: Unit.h:2473
bool isMoving() const
Definition: Unit.h:2449
virtual bool SetWalk(bool enable)
Definition: Unit.cpp:19660
SpellMissInfo MeleeSpellHitResult(Unit *victim, SpellInfo const *spell)
Definition: Unit.cpp:2810
Aura * _TryStackingOrRefreshingExistingAura(SpellInfo const *newAura, uint8 effMask, Unit *caster, int32 *baseAmount=nullptr, Item *castItem=nullptr, ObjectGuid casterGUID=ObjectGuid::Empty, bool periodicReset=false)
Definition: Unit.cpp:3882
void setRace(uint8 race)
Definition: Unit.cpp:20041
virtual bool UpdateStats(Stats stat)=0
void BuildCooldownPacket(WorldPacket &data, uint8 flags, uint32 spellId, uint32 cooldown)
Definition: Unit.cpp:20007
void SendHealSpellLog(Unit *victim, uint32 SpellID, uint32 Damage, uint32 OverHeal, uint32 Absorb, bool critical=false)
Definition: Unit.cpp:10604
void RemoveAllDynObjects()
Definition: Unit.cpp:5634
uint32 GetArmor() const
Definition: Unit.h:1551
float m_modMeleeHitChance
Definition: Unit.h:2172
void RemoveArenaAuras()
Definition: Unit.cpp:4834
void _RemoveAllAuraStatMods()
Definition: Unit.cpp:4977
SpellCastResult CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=nullptr, AuraEffect const *triggeredByAura=nullptr, ObjectGuid originalCaster=ObjectGuid::Empty)
Definition: Unit.cpp:1087
void SetPhaseMask(uint32 newPhaseMask, bool update) override
Definition: Unit.cpp:18163
uint32 GetAttackTime(WeaponAttackType att) const
Definition: Unit.h:1588
ObjectGuid GetCritterGUID() const
Definition: Unit.h:1906
uint16 GetExtraUnitMovementFlags() const
Definition: Unit.h:2361
Unit * GetMagicHitRedirectTarget(Unit *victim, SpellInfo const *spellInfo)
Definition: Unit.cpp:10396
AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraApplication *except=nullptr) const
Definition: Unit.cpp:5082
TempSummon * ToTempSummon()
Definition: Unit.h:2469
ObjectGuid GetCharmGUID() const
Definition: Unit.h:1902
void StopAttackFaction(uint32 faction_id)
Definition: Unit.cpp:19222
uint32 GetCastingTimeForBonus(SpellInfo const *spellProto, DamageEffectType damagetype, uint32 CastingTime) const
Definition: Unit.cpp:16287
bool IsFFAPvP() const
Definition: Unit.h:1625
void RemoveAreaAurasDueToLeaveWorld()
Definition: Unit.cpp:4785
static uint32 SpellCriticalHealingBonus(Unit const *caster, SpellInfo const *spellProto, uint32 damage, Unit const *victim)
Definition: Unit.cpp:11664
bool CanModifyStats() const
Definition: Unit.h:2192
void BuildMovementPacket(ByteBuffer *data) const
Definition: Unit.cpp:18964
void RemoveCharmedBy(Unit *charmer)
Definition: Unit.cpp:17671
bool CreateVehicleKit(uint32 id, uint32 creatureEntry)
Definition: Unit.cpp:17832
bool IsMounted() const
Definition: Unit.h:1648
int32 ModifyPowerPct(Powers power, float pct, bool apply=true)
Definition: Unit.cpp:13361
bool IsWithinRange(Unit const *obj, float dist) const
Definition: Unit.cpp:662
void _ApplyAura(AuraApplication *aurApp, uint8 effMask)
Definition: Unit.cpp:4032
virtual void SetDisplayId(uint32 modelId)
Definition: Unit.cpp:16071
void SendPetAIReaction(ObjectGuid guid)
Definition: Unit.cpp:15973
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:4420
virtual float GetFollowAngle() const
Definition: Unit.h:2461
void CleanupBeforeRemoveFromMap(bool finalCleanup)
Definition: Unit.cpp:14860
uint8 getStandState() const
Definition: Unit.h:1640
bool IsGuardian() const
Definition: Unit.h:1532
Position m_last_notify_position
Definition: Unit.h:2478
MotionMaster * GetMotionMaster()
Definition: Unit.h:2345
Vehicle * m_vehicleKit
Definition: Unit.h:2600
void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
Definition: Unit.cpp:5781
float GetCollisionWidth() const override
this method gets the diameter of a Unit by DB if any value is defined, otherwise it gets the value by...
Definition: Unit.cpp:20073
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask, bool isDoT=false)
Definition: Unit.cpp:11315
float GetAPMultiplier(WeaponAttackType attType, bool normalized)
Definition: Unit.cpp:16427
void UpdateOrientation(float orientation)
Only server-side orientation update, does not broadcast to client.
Definition: Unit.cpp:19118
uint32 GetMeleeCritDamageReduction(uint32 damage) const
Definition: Unit.h:1683
virtual bool IsUnderWater() const
Definition: Unit.cpp:3872
void SendEnergizeSpellLog(Unit *victim, uint32 SpellID, uint32 Damage, Powers powertype)
Definition: Unit.cpp:10633
void StopMovingOnCurrentPos()
Definition: Unit.cpp:16006
float GetUnitBlockChance() const
Definition: Unit.cpp:3255
void RemovePlayerFromVision(Player *player)
Definition: Unit.cpp:10558
CharmThreatMap _charmThreatInfo
Definition: Unit.h:2597
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
Definition: Unit.cpp:12076
float GetCreateStat(Stats stat) const
Definition: Unit.h:2124
void UpdateSplinePosition()
Definition: Unit.cpp:584
void SetOwnerGUID(ObjectGuid owner)
Definition: Unit.cpp:9967
CharmInfo * GetCharmInfo()
Definition: Unit.h:1963
float SpellPctHealingModsDone(Unit *victim, SpellInfo const *spellProto, DamageEffectType damagetype)
Definition: Unit.cpp:11703
Unit * GetFirstControlled() const
Definition: Unit.cpp:10452
void SetSpeed(UnitMoveType mtype, float rate, bool forced=false)
Definition: Unit.cpp:13589
ObjectGuid GetTransGUID() const override
Definition: Unit.cpp:17873
bool IsAIEnabled
Definition: Unit.h:2419
void ApplyCastTimePercentMod(float val, bool apply)
Definition: Unit.cpp:16279
Vehicle * GetVehicleKit() const
Definition: Unit.h:2422
bool IsCritter() const
Definition: Unit.h:1766
void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
Definition: Unit.cpp:1590
virtual bool IsImmunedToSpellEffect(SpellInfo const *spellInfo, uint32 index) const
Definition: Unit.cpp:12232
bool HasUnitState(const uint32 f) const
Definition: Unit.h:1519
Player * GetAffectingPlayer() const
Definition: Unit.cpp:10019
uint32 GetSpellDamageReduction(uint32 damage) const
Definition: Unit.h:1690
float SpellPctDamageModsDone(Unit *victim, SpellInfo const *spellProto, DamageEffectType damagetype)
Definition: Unit.cpp:10657
void FinishSpell(CurrentSpellTypes spellType, bool ok=true)
Definition: Unit.cpp:3614
void Update(uint32 time) override
Definition: Unit.cpp:387
void ModSpellCastTime(SpellInfo const *spellProto, int32 &castTime, Spell *spell=nullptr)
Definition: Unit.cpp:14130
bool IsInRaidWith(Unit const *unit) const
Definition: Unit.cpp:17914
GameObjectList m_gameObj
Definition: Unit.h:2561
AuraMap m_ownedAuras
Definition: Unit.h:2566
void ProcessPositionDataChanged(PositionFullTerrainStatus const &data) override
Definition: Unit.cpp:3782
Unit(bool isWorldObject)
Definition: Unit.cpp:195
bool IsInFeralForm() const
Definition: Unit.h:2159
void SendMeleeAttackStart(Unit *victim, Player *sendTo=nullptr)
Definition: Unit.cpp:2725
uint32 MeleeDamageBonusTaken(Unit *attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const *spellProto=nullptr)
Definition: Unit.cpp:12491
void BuildHeartBeatMsg(WorldPacket *data) const
Definition: Object.cpp:2179
HostileRefMgr m_HostileRefMgr
Definition: Unit.h:2641
bool IsFriendlyTo(Unit const *unit) const
Definition: Unit.cpp:9649
std::pair< AuraMap::iterator, AuraMap::iterator > AuraMapBoundsNonConst
Definition: Unit.h:1426
void RemoveUnitMovementFlag(uint32 f)
Definition: Unit.h:2353
void RemoveBindSightAuras()
Definition: Unit.cpp:10569
int32 GetMaxNegativeAuraModifier(AuraType auratype) const
Definition: Unit.cpp:5425
AuraApplicationMap m_appliedAuras
Definition: Unit.h:2567
int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
Definition: Unit.cpp:5490
CharmInfo * InitCharmInfo()
Definition: Unit.cpp:14929
ObjectGuid GetOwnerGUID() const
Definition: Unit.h:1894
void RemoveAllAttackers()
Definition: Unit.cpp:9878
virtual bool CanSwim() const
this method checks the current flag of a unit
Definition: Unit.cpp:19028
uint32 GetDoTsByCaster(ObjectGuid casterGUID) const
Definition: Unit.cpp:5343
bool IsControllableGuardian() const
Definition: Unit.h:1533
void RemoveFromWorld() override
Definition: Unit.cpp:14814
bool IsWithinMeleeRange(const Unit *obj, float dist=0.f) const
Definition: Unit.cpp:641
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
Definition: Unit.cpp:11277
void AttackerStateUpdate(Unit *victim, WeaponAttackType attType=BASE_ATTACK, bool extra=false)
Definition: Unit.cpp:2281
Unit * SelectNearbyNoTotemTarget(Unit *exclude=nullptr, float dist=NOMINAL_MELEE_RANGE) const
Definition: Unit.cpp:16228
virtual void UpdateMaxHealth()=0
uint32 HasUnitTypeMask(uint32 mask) const
Definition: Unit.h:1528
void SendClearThreatListOpcode()
Definition: Unit.cpp:19174
void _RegisterAuraEffect(AuraEffect *aurEff, bool apply)
Definition: Unit.cpp:4213
void SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo)
Definition: Unit.cpp:5834
void ClearInCombat()
Definition: Unit.cpp:12992
uint32 CountPctFromMaxHealth(int32 pct) const
Definition: Unit.h:1568
void _EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const *aurApp=nullptr)
Definition: Unit.cpp:18725
float GetMeleeRange(Unit const *target) const
Definition: Unit.cpp:656
bool isDying() const
Definition: Unit.h:1889
bool isTargetableForAttack(bool checkFakeDeath=true, Unit const *byWho=nullptr) const
Definition: Unit.cpp:13036
float GetStat(Stats stat) const
Definition: Unit.h:1549
void SendMeleeAttackStop(Unit *victim=nullptr)
Definition: Unit.cpp:2737
void UpdateSpeed(UnitMoveType mtype, bool forced)
Definition: Unit.cpp:13424
int32 getAttackTimer(WeaponAttackType type) const
Definition: Unit.h:1468
void CastDelayedSpellWithPeriodicAmount(Unit *caster, uint32 spellId, AuraType auraType, int32 addAmount, uint8 effectIndex=0)
Definition: Unit.cpp:19315
bool m_applyResilience
Definition: Unit.h:2606
void RemoveAllAuras()
Definition: Unit.cpp:4818
bool IsControlledByPlayer() const
Definition: Unit.h:1908
void RestoreDisplayId()
Definition: Unit.cpp:16079
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition: Unit.cpp:5450
void HandleEmoteCommand(uint32 anim_id)
Definition: Unit.cpp:1721
bool m_canDualWield
Definition: Unit.h:1481
int32 GetMaxNegativeAuraModifierByAffectMask(AuraType auratype, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:5580
ObjectGuid GetCharmerGUID() const
Definition: Unit.h:1900
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const
Definition: Unit.cpp:15932
Minion * GetFirstMinion() const
Definition: Unit.cpp:10030
bool HandleSpellClick(Unit *clicker, int8 seatId=-1)
Definition: Unit.cpp:18632
UnitAI * GetAI()
Definition: Unit.h:1445
bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura=0) const
Definition: Unit.cpp:740
bool SetCharmedBy(Unit *charmer, CharmType type, AuraApplication const *aurApp=nullptr)
Definition: Unit.cpp:17487
bool IsAlwaysVisibleFor(WorldObject const *seer) const override
Definition: Unit.cpp:13369
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:1564
void SetPetGUID(ObjectGuid guid)
Definition: Unit.h:1903
uint32 getTransForm() const
Definition: Unit.h:2259
float GetUnitParryChance() const
Definition: Unit.cpp:3210
bool HasSharedVision() const
Definition: Unit.h:1972
PetAuraSet m_petAuras
Definition: Unit.h:2403
virtual bool SetDisableGravity(bool disable, bool packetOnly=false)
Definition: Unit.cpp:19674
Powers getPowerType() const
Definition: Unit.h:1578
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const *spellInfo=nullptr, uint8 effIndex=MAX_SPELL_EFFECTS)
Definition: Unit.cpp:1729
void SetMaxHealth(uint32 val)
Definition: Unit.cpp:14669
void SetCreatorGUID(ObjectGuid creator)
Definition: Unit.h:1897
void GetPartyMembers(std::list< Unit * > &units)
Definition: Unit.cpp:17936
void RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID=ObjectGuid::Empty, Aura *except=nullptr, bool negative=true, bool positive=true)
Definition: Unit.cpp:4610
uint32 GetPower(Powers power) const
Definition: Unit.h:1580
uint32 m_interruptMask
Definition: Unit.h:2576
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const
Definition: Unit.cpp:18293
void SendMovementFeatherFall(Player *sendTo)
Definition: Unit.cpp:19764
int32 GetTotalAuraModifier(AuraType auratype) const
Definition: Unit.cpp:5386
uint32 GetMeleeDamageReduction(uint32 damage) const
Definition: Unit.h:1688
void SendChangeCurrentVictimOpcode(HostileReference *pHostileReference)
Definition: Unit.cpp:19153
uint32 GetCreatureTypeMask() const
Definition: Unit.h:1634
bool InitTamedPet(Pet *pet, uint8 level, uint32 spell_id)
Definition: Unit.cpp:16590
bool IsFlying() const
Definition: Unit.h:2454
void SetCritterGUID(ObjectGuid guid)
Definition: Unit.h:1905
uint8 getLevel() const
Definition: Unit.h:1539
std::list< AuraEffect * > AuraEffectList
Definition: Unit.h:1435
void RemoveMovementImpairingAuras(bool withRoot)
Definition: Unit.cpp:4728
bool isAttackReady(WeaponAttackType type=BASE_ATTACK) const
Definition: Unit.h:1469
int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition: Unit.cpp:5476
void ClearDiminishings()
Definition: Unit.h:1458
void GetDispellableAuraList(Unit *caster, uint32 dispelMask, DispelChargesList &dispelList)
Definition: Unit.cpp:5100
VisibleAuraMap m_visibleAuras
Definition: Unit.h:2581
uint32 GetCreateMana() const
Definition: Unit.h:2120
bool IsTotem() const
Definition: Unit.h:1536
void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, Unit *stealer)
Definition: Unit.cpp:4517
void ChangeSeat(int8 seatId, bool next=true)
Definition: Unit.cpp:18788
void GetProcAurasTriggeredOnEvent(std::list< AuraApplication * > &aurasTriggeringProc, std::list< AuraApplication * > *procAuras, ProcEventInfo eventInfo)
Definition: Unit.cpp:15868
void SetInFront(WorldObject const *target)
Definition: Unit.cpp:19631
void ApplyDiminishingAura(DiminishingGroup group, bool apply)
Definition: Unit.cpp:14283
void ApplySpellDispelImmunity(const SpellInfo *spellProto, DispelType type, bool apply)
Definition: Unit.cpp:12631
int32 GetMaxPositiveAuraModifierByAffectMask(AuraType auratype, SpellInfo const *affectedSpell) const
Definition: Unit.cpp:5566
AuraStateAurasMap m_auraStateAuras
Definition: Unit.h:2575
float m_speed_rate[MAX_MOVE_TYPE]
Definition: Unit.h:2583
void setPowerType(Powers power)
Definition: Unit.cpp:9418
bool IsAlwaysDetectableFor(WorldObject const *seer) const override
Definition: Unit.cpp:13388
bool IsValidAssistTarget(Unit const *target) const
Definition: Unit.cpp:13173
float m_modSpellHitChance
Definition: Unit.h:2174
void TriggerAurasProcOnEvent(CalcDamageInfo &damageInfo)
Definition: Unit.cpp:15898
bool IsImmunedToDamageOrSchool(SpellSchoolMask meleeSchoolMask) const
Definition: Unit.cpp:12143
Guardian * GetGuardianPet() const
Definition: Unit.cpp:10045
uint32 SpellHealingBonusDone(Unit *victim, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, float TotalMod=0.0f, uint32 stack=1)
Definition: Unit.cpp:11795
void resetAttackTimer(WeaponAttackType type=BASE_ATTACK)
Definition: Unit.cpp:619
void SendThreatListUpdate()
Definition: Unit.cpp:19133
virtual void Talk(std::string_view text, ChatMsg msgType, Language language, float textRange, WorldObject const *target)
Definition: Unit.cpp:20141
bool IsHostileTo(Unit const *unit) const
Definition: Unit.cpp:9644
UnitAI * i_disabledAI
Definition: Unit.h:2534
uint32 SpellHealingBonusTaken(Unit *caster, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack=1)
Definition: Unit.cpp:11904
AuraEffectList m_modAuras[TOTAL_AURAS]
Definition: Unit.h:2572
void SetStandState(uint8 state)
Definition: Unit.cpp:16043
void _ApplyAuraEffect(Aura *aura, uint8 effIndex)
Definition: Unit.cpp:4018
void DeMorph()
Definition: Unit.cpp:3877
void RemoveAllMinionsByEntry(uint32 entry)
Definition: Unit.cpp:10250
virtual void Whisper(std::string_view text, Language language, Player *target, bool isBossWhisper=false)
Definition: Unit.cpp:20164
bool IsFalling() const
Definition: Unit.cpp:19016
bool AttackStop()
Definition: Unit.cpp:9802
void KnockbackFrom(float x, float y, float speedXY, float speedZ)
Definition: Unit.cpp:18242
int32 GetCurrentSpellCastTime(uint32 spell_id) const
Definition: Unit.cpp:3679
static void HandleSafeUnitPointersOnDelete(Unit *thisUnit)
Definition: Unit.cpp:3857
float CalculateLevelPenalty(SpellInfo const *spellProto) const
Definition: Unit.cpp:2704
void GetAllMinionsByEntry(std::list< Creature * > &Minions, uint32 entry)
Definition: Unit.cpp:10238
bool IsInPartyWith(Unit const *unit) const
Definition: Unit.cpp:17891
static void CalcAbsorbResist(DamageInfo &dmgInfo, bool Splited=false)
Definition: Unit.cpp:1875
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition: Unit.h:2047
ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT]
Definition: Unit.h:2150
void RemovePointedBy(SafeUnitPointer *sup)
Definition: Unit.h:2475
bool m_cleanupDone
Definition: Unit.h:2650
static void DealDamageMods(Unit const *victim, uint32 &damage, uint32 *absorb)
Definition: Unit.cpp:763
SharedVisionList m_sharedVision
Definition: Unit.h:2586
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask)
Definition: Unit.cpp:12064
bool HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const
Definition: Unit.cpp:5218
AuraMap & GetOwnedAuras()
Definition: Unit.h:1994
void RemoveCharmAuras()
Definition: Unit.cpp:10574
bool IsInCombat() const
Definition: Unit.h:1770
bool IsWalking() const
Definition: Unit.h:2448
ThreatMgr & getThreatMgr()
Definition: Unit.h:2233
float GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo *spellProto) const
Definition: Unit.cpp:12666
int32 GetTotalAuraModifierAreaExclusive(AuraType auratype) const
Definition: Unit.cpp:5366
Unit * GetCharmerOrOwnerOrSelf() const
Definition: Unit.h:1928
bool IsSitState() const
Definition: Unit.cpp:16028
virtual void SetTarget(ObjectGuid=ObjectGuid::Empty)=0
void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellInfo const *spellInfo, WeaponAttackType attackType=BASE_ATTACK, bool crit=false)
Definition: Unit.cpp:1215
Unit * GetVictim() const
Definition: Unit.h:1508
uint16 m_delayed_unit_relocation_timer
Definition: Unit.h:2480
float m_threatModifier[MAX_SPELL_SCHOOL]
Definition: Unit.h:2177
void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, Player *target) const override
Definition: Unit.cpp:19810
virtual bool SetWaterWalking(bool enable, bool packetOnly=false)
Definition: Unit.cpp:19729
void RemoveAllControlled(bool onDeath=false)
Definition: Unit.cpp:10463
bool _IsValidAttackTarget(Unit const *target, SpellInfo const *bySpell, WorldObject const *obj=nullptr) const
Definition: Unit.cpp:13059
float GetWeaponProcChance() const
Definition: Unit.cpp:12655
ObjectGuid GetPetGUID() const
Definition: Unit.h:1904
float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *victim) const
Definition: Unit.cpp:3281
uint32 m_lastManaUse
Definition: Unit.h:2636
bool CanMoveDuringChannel() const
Definition: Unit.cpp:3710
void ExitVehicle(Position const *exitPosition=nullptr)
Definition: Unit.cpp:18807
ObjectGuid GetCharmerOrOwnerGUID() const
Definition: Unit.h:1910
void CombatStopWithPets(bool includingCast=false)
Definition: Unit.cpp:9851
bool BuildPacket(WorldPacket *packet)
Definition: UpdateData.cpp:105
uint32 GetBlockCount() const
Definition: UpdateMask.h:63
bool GetBit(uint32 index) const
Definition: UpdateMask.h:48
void UnsetBit(uint32 index)
Definition: UpdateMask.h:47
void SetCount(uint32 valuesCount)
Definition: UpdateMask.h:66
void SetBit(uint32 index)
Definition: UpdateMask.h:46
void AppendToPacket(ByteBuffer *data)
Definition: UpdateMask.h:50
bool Execute(uint64 e_time, uint32 p_time) override
Definition: Unit.cpp:18832
uint32 _duration
Definition: Unit.h:2745
Unit * GetBase() const
May be called from scripts.
Definition: Vehicle.h:39
int8 GetNextEmptySeat(int8 seatId, bool next) const
Definition: Vehicle.cpp:235
void Dismiss()
Definition: Vehicle.cpp:523
void Reset(bool evading=false)
Definition: Vehicle.cpp:118
void RemovePassenger(Unit *passenger)
Definition: Vehicle.cpp:444
VehicleEntry const * GetVehicleInfo() const
Definition: Vehicle.h:40
bool AddPassenger(Unit *passenger, int8 seatId=-1)
Definition: Vehicle.cpp:307
uint32 GetCreatureEntry() const
Definition: Vehicle.h:41
void Uninstall()
Definition: Vehicle.cpp:101
bool HasEmptySeat(int8 seatId) const
Definition: Vehicle.cpp:218
void RelocatePassengers()
Definition: Vehicle.cpp:498
void InstallAllAccessories(bool evading)
Definition: Vehicle.cpp:87
static uint32 GetGameTimeMS()
What time is it? in ms.
Definition: World.h:246
uint32 GetMapId() const
Definition: Object.h:486
int8 GetTransSeat() const
Definition: Object.h:873
virtual void SetPhaseMask(uint32 newPhaseMask, bool update)
Definition: Object.cpp:2945
uint32 GetPhaseMask() const
Definition: Object.h:717
std::string const & GetName() const
Definition: Object.h:729
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition: Object.cpp:1718
void AddToWorld() override
Definition: Object.cpp:1224
void RemoveFromWorld() override
Definition: Object.cpp:1230
virtual void SendMessageToSet(WorldPacket *data, bool self)
Definition: Object.h:765
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1240
virtual bool IsAlwaysDetectableFor(WorldObject const *) const
Definition: Object.h:928
float GetMapHeight(float x, float y, float z, bool vmap=true, float distanceToSearch=50.0f) const
Definition: Object.cpp:3165
void SetWorldObject(bool apply)
Definition: Object.cpp:1117
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool useBoundingRadius=true) const
Definition: Object.cpp:1364
void SetTransport(Transport *t)
Definition: Object.h:875
float GetTransOffsetX() const
Definition: Object.h:868
void MovePositionToFirstCollision(Position &pos, float dist, float angle)
Definition: Object.cpp:2930
LiquidData const & GetLiquidData() const
Definition: Object.cpp:3224
void GetContactPoint(const WorldObject *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition: Object.cpp:2814
Map * FindMap() const
Definition: Object.h:801
uint32 GetInstanceId() const
Definition: Object.h:714
void setActive(bool isActiveObject)
Definition: Object.cpp:1136
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle, float controlZ=0, Position const *startPos=nullptr) const
Definition: Object.cpp:2698
Map * GetMap() const
Definition: Object.h:800
float GetDistance(const WorldObject *obj) const
Definition: Object.cpp:1293
float GetTransOffsetY() const
Definition: Object.h:869
float GetFloorZ() const
Definition: Object.cpp:3180
float GetTransOffsetZ() const
Definition: Object.h:870
virtual bool IsAlwaysVisibleFor(WorldObject const *) const
Definition: Object.h:925
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS) const
Definition: Object.cpp:1374
bool InSamePhase(WorldObject const *obj) const
Definition: Object.h:718
virtual void ProcessPositionDataChanged(PositionFullTerrainStatus const &data)
Definition: Object.cpp:1211
Transport * GetTransport() const
Definition: Object.h:867
void RemoveFromNotify(uint16 f)
Definition: Object.h:836
uint32 GetTransTime() const
Definition: Object.h:872
ZoneScript * GetZoneScript() const
Definition: Object.h:806
void AddToNotify(uint16 f)
Definition: Object.cpp:3023
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool useBoundingRadius=true) const
Definition: Object.cpp:1369
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS) const
Definition: Object.cpp:1395
float GetTransOffsetO() const
Definition: Object.h:871
uint32 GetZoneId() const
Definition: Object.cpp:3191
MovementInfo m_movementInfo
Definition: Object.h:877
bool IsInMap(const WorldObject *obj) const
Definition: Object.cpp:1333
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibility
Definition: Object.h:792
bool CanSeeOrDetect(WorldObject const *obj, bool ignoreStealth=false, bool distanceCheck=false, bool checkAlert=false) const
Definition: Object.cpp:1885
float GetObjectSize() const
Definition: Object.cpp:2843
virtual void UpdateObjectVisibility(bool forced=true, bool fromUpdate=false)
Definition: Object.cpp:3016
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
AccountTypes GetSecurity() const
Definition: WorldSession.h:269
LocaleConstant GetSessionDbLocaleIndex() const
Definition: WorldSession.h:408
bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const
Definition: Util.h:500
bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const
Definition: Util.h:495
spellIdImmunityPredicate(uint32 type)
Definition: Unit.cpp:12597
bool operator()(SpellImmune const &spellImmune)
Definition: Unit.cpp:12598
Definition: core.h:1120
FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT
Definition: color.h:363
static Bigint * diff(Bigint *a, Bigint *b, Stack_alloc *alloc)
Definition: dtoa.c:1108
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2078
basic_string_view< char > string_view
Definition: core.h:529
constexpr auto count() -> size_t
Definition: core.h:1039
type
Definition: core.h:1048
@ SMSG_SPELLENERGIZELOG
Definition: Opcodes.h:367
@ SMSG_FORCE_TURN_RATE_CHANGE
Definition: Opcodes.h:764
@ SMSG_PARTYKILLLOG
Definition: Opcodes.h:531
@ MSG_MOVE_SET_SWIM_BACK_SPEED
Definition: Opcodes.h:243
@ MSG_MOVE_SET_TURN_RATE
Definition: Opcodes.h:246
@ SMSG_FORCE_WALK_SPEED_CHANGE
Definition: Opcodes.h:760
@ SMSG_PLAY_SPELL_VISUAL
Definition: Opcodes.h:529
@ SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE
Definition: Opcodes.h:929
@ SMSG_SPELLLOGMISS
Definition: Opcodes.h:617
@ SMSG_PET_TAME_FAILURE
Definition: Opcodes.h:401
@ SMSG_PET_ACTION_FEEDBACK
Definition: Opcodes.h:740
@ SMSG_SPELLORDAMAGE_IMMUNE
Definition: Opcodes.h:641
@ SMSG_FORCE_MOVE_UNROOT
Definition: Opcodes.h:264
@ MSG_MOVE_SET_PITCH_RATE
Definition: Opcodes.h:1145
@ SMSG_MOVE_KNOCK_BACK
Definition: Opcodes.h:269
@ SMSG_FORCE_RUN_SPEED_CHANGE
Definition: Opcodes.h:256
@ SMSG_SPELLNONMELEEDAMAGELOG
Definition: Opcodes.h:622
@ SMSG_FORCE_SWIM_BACK_SPEED_CHANGE
Definition: Opcodes.h:762
@ SMSG_PROCRESIST
Definition: Opcodes.h:638
@ SMSG_FORCE_RUN_BACK_SPEED_CHANGE
Definition: Opcodes.h:258
@ SMSG_BREAK_TARGET
Definition: Opcodes.h:368
@ SMSG_MONSTER_MOVE
Definition: Opcodes.h:251
@ SMSG_FORCE_FLIGHT_SPEED_CHANGE
Definition: Opcodes.h:927
@ SMSG_LOOT_LIST
Definition: Opcodes.h:1047
@ SMSG_FORCE_SWIM_SPEED_CHANGE
Definition: Opcodes.h:260
@ SMSG_FORCE_MOVE_ROOT
Definition: Opcodes.h:262
@ SMSG_THREAT_UPDATE
Definition: Opcodes.h:1185
@ SMSG_PLAYER_VEHICLE_DATA
Definition: Opcodes.h:1221
@ SMSG_PLAY_SPELL_IMPACT
Definition: Opcodes.h:533
@ SMSG_SPELL_COOLDOWN
Definition: Opcodes.h:338
@ SMSG_HIGHEST_THREAT_UPDATE
Definition: Opcodes.h:1184
@ MSG_MOVE_SET_RUN_SPEED
Definition: Opcodes.h:235
@ SMSG_THREAT_CLEAR
Definition: Opcodes.h:1187
@ SMSG_MOVE_SET_COLLISION_HGT
Definition: Opcodes.h:1332
@ SMSG_EMOTE
Definition: Opcodes.h:289
@ SMSG_PET_ACTION_SOUND
Definition: Opcodes.h:834
@ SMSG_SPLINE_MOVE_SET_HOVER
Definition: Opcodes.h:805
@ SMSG_SPELLDAMAGESHIELD
Definition: Opcodes.h:621
@ MSG_MOVE_SET_FLIGHT_SPEED
Definition: Opcodes.h:924
@ MSG_MOVE_SET_WALK_SPEED
Definition: Opcodes.h:239
@ SMSG_THREAT_REMOVE
Definition: Opcodes.h:1186
@ MSG_MOVE_SET_SWIM_SPEED
Definition: Opcodes.h:241
@ MSG_MOVE_TELEPORT
Definition: Opcodes.h:227
@ MSG_MOVE_SET_FLIGHT_BACK_SPEED
Definition: Opcodes.h:926
@ SMSG_SPLINE_MOVE_UNROOT
Definition: Opcodes.h:802
@ SMSG_ATTACKSTOP
Definition: Opcodes.h:354
@ SMSG_ATTACKSTART
Definition: Opcodes.h:353
@ SMSG_DISMOUNT
Definition: Opcodes.h:970
@ SMSG_DURABILITY_DAMAGE_DEATH
Definition: Opcodes.h:731
@ SMSG_SPELLHEALLOG
Definition: Opcodes.h:366
@ SMSG_SPLINE_MOVE_FEATHER_FALL
Definition: Opcodes.h:803
@ SMSG_SPLINE_MOVE_ROOT
Definition: Opcodes.h:824
@ SMSG_ATTACKERSTATEUPDATE
Definition: Opcodes.h:360
@ SMSG_AI_REACTION
Definition: Opcodes.h:346
@ SMSG_STANDSTATE_UPDATE
Definition: Opcodes.h:699
@ SMSG_FORCE_PITCH_RATE_CHANGE
Definition: Opcodes.h:1146
@ SMSG_POWER_UPDATE
Definition: Opcodes.h:1182
@ SMSG_PERIODICAURALOG
Definition: Opcodes.h:620
@ SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA
Definition: Opcodes.h:1211
@ SMSG_SPLINE_MOVE_WATER_WALK
Definition: Opcodes.h:807
@ MSG_MOVE_SET_RUN_BACK_SPEED
Definition: Opcodes.h:237
#define sWorld
Definition: World.h:511
@ PLAYER_UPDATE_DATA_LEVEL
Definition: World.h:148
unsigned short uint16
Definition: my_global.h:887
signed char int8
Definition: my_global.h:878
ulonglong uint64
Definition: my_global.h:928
#define min(a, b)
Definition: my_global.h:1387
unsigned char uint8
Definition: my_global.h:881
#define M_PI
Definition: my_global.h:819
#define max(a, b)
Definition: my_global.h:1386
bool IsGMAccount(uint32 gmlevel)
Definition: AccountMgr.cpp:281
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:135
bool IsValidMapCoord(float c)
Definition: GridDefines.h:216
void SendCommand_UInt32Value(T *o, ObjectGuid targetGUID, const char *prefix, uint32 t)
void apply(T *val)
Definition: ByteConverter.h:40
bool IsPathfindingEnabled(const Map *map)
Definition: DisableMgr.cpp:392
G3D::int16 z
Definition: Vector3int16.h:46
static Vector3int16 floor(const Vector3 &v)
static Vector3int16 ceil(const Vector3 &v)
bool fuzzyGt(double a, double b)
Definition: g3dmath.h:865
static void var(TextOutput &t, const std::string &name, const std::string &val)
Definition: System.cpp:1584
G3D::int16 x
Definition: Vector2int16.h:37
bool fuzzyEq(double a, double b)
Definition: g3dmath.h:857
G3D::int16 y
Definition: Vector2int16.h:38
bool any(float x)
Definition: g3dmath.h:424
double frand()
Definition: Vector3.cpp:170
Quat log(const Quat &q)
Definition: Quat.h:733
double distance(double x, double y)
Definition: g3dmath.h:731
uint16_t uint16
Definition: g3dmath.h:166
uint32_t uint32
Definition: g3dmath.h:168
uint8_t uint8
Definition: g3dmath.h:164
int32_t int32
Definition: g3dmath.h:167
Definition: Unit.h:836
Unit * GetUnit(WorldObject const &, ObjectGuid const guid)
GameObject * GetGameObject(WorldObject const &u, ObjectGuid const guid)
Pet * GetPet(WorldObject const &, ObjectGuid const guid)
Player * FindPlayer(ObjectGuid const guid)
Creature * GetCreatureOrPetOrVehicle(WorldObject const &, ObjectGuid const)
Creature * GetCreature(WorldObject const &u, ObjectGuid const guid)
Player * GetPlayer(Map const *, ObjectGuid const guid)
remove_cvref_t< decltype(*detail::range_begin(std::declval< Range >()))> value_type
Definition: ranges.h:246
a
Definition: mpq.py:290
list c
Definition: mpq.py:295
void advance(octet_iterator &it, distance_type n, octet_iterator end)
Definition: checked.h:190
#define LOG_FATAL(filterType__,...)
Definition: Log.h:257
#define LOG_INFO(filterType__,...)
Definition: Log.h:269
#define LOG_ERROR(filterType__,...)
Definition: Log.h:261
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:273
int32 irand(int32 min, int32 max)
Definition: Random.cpp:37
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:44
double rand_norm()
Definition: Random.cpp:77
bool roll_chance_f(float chance)
Definition: Random.h:53
bool roll_chance_i(int chance)
Definition: Random.h:59
T AddPct(T &base, U pct)
Definition: Util.h:104
T RoundToInterval(T &num, T floor, T ceil)
Definition: Util.h:116
T ApplyPct(T &base, U pct)
Definition: Util.h:110
void ApplyPercentModFloatVar(float &var, float val, bool apply)
Definition: Util.h:87
T CalculatePct(T base, U pct)
Definition: Util.h:98
LocaleConstant
Definition: Common.h:74
constexpr auto IN_MILLISECONDS
Definition: Common.h:62
@ SEC_PLAYER
Definition: Common.h:66
@ SEC_GAMEMASTER
Definition: Common.h:68
constexpr auto MINUTE
Definition: Common.h:56
std::string const & GetText(LocaleConstant locale=DEFAULT_LOCALE, uint8 gender=GENDER_MALE, bool forceGender=false) const
Definition: ObjectMgr.h:456
uint32 damageSchoolMask
Definition: Unit.h:1018
uint32 blocked_amount
Definition: Unit.h:1022
MeleeHitOutcome hitOutCome
Definition: Unit.h:1031
uint32 procAttacker
Definition: Unit.h:1027
uint32 procVictim
Definition: Unit.h:1028
uint32 cleanDamage
Definition: Unit.h:1030
uint32 absorb
Definition: Unit.h:1020
uint32 TargetState
Definition: Unit.h:1024
uint32 resist
Definition: Unit.h:1021
uint32 damage
Definition: Unit.h:1019
uint32 procEx
Definition: Unit.h:1029
uint32 HitInfo
Definition: Unit.h:1023
Unit * attacker
Definition: Unit.h:1016
Unit * target
Definition: Unit.h:1017
WeaponAttackType attackType
Definition: Unit.h:1026
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:207
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:193
void RestoreState()
Definition: Unit.cpp:14966
void RemoveStayPosition()
Definition: Unit.cpp:19402
CharmInfo(Unit *unit)
Definition: Unit.cpp:14947
float _stayY
Definition: Unit.h:1299
void SetIsCommandFollow(bool val)
Definition: Unit.cpp:19362
bool IsCommandAttack()
Definition: Unit.cpp:19357
void LoadPetActionBar(const std::string &data)
Definition: Unit.cpp:15153
bool AddSpellToActionBar(SpellInfo const *spellInfo, ActiveStates newstate=ACT_DECIDE)
Definition: Unit.cpp:15085
void SetActionBar(uint8 index, uint32 spellOrAction, ActiveStates type)
Definition: Unit.h:1245
bool _isAtStay
Definition: Unit.h:1293
void InitPossessCreateSpells()
Definition: Unit.cpp:14997
void SetIsAtStay(bool val)
Definition: Unit.cpp:19414
bool IsFollowing()
Definition: Unit.cpp:19429
float _stayX
Definition: Unit.h:1298
void SetPetNumber(uint32 petnumber, bool statwindow)
Definition: Unit.cpp:15144
float _stayZ
Definition: Unit.h:1300
bool IsReturning()
Definition: Unit.cpp:19439
void SetIsFollowing(bool val)
Definition: Unit.cpp:19424
void InitPetActionBar()
Definition: Unit.cpp:14972
bool _isCommandFollow
Definition: Unit.h:1292
UnitActionBarEntry PetActionBar[MAX_UNIT_ACTION_BAR_INDEX]
Definition: Unit.h:1283
~CharmInfo()
Definition: Unit.cpp:14962
void SetIsReturning(bool val)
Definition: Unit.cpp:19434
void SaveStayPosition(bool atCurrentPos)
Definition: Unit.cpp:19372
void InitCharmCreateSpells()
Definition: Unit.cpp:15033
void BuildActionBar(WorldPacket *data)
Definition: Unit.cpp:15183
bool RemoveSpellFromActionBar(uint32 spell_id)
Definition: Unit.cpp:15115
void SetForcedSpell(uint32 id)
Definition: Unit.h:1272
void SetSpellAutocast(SpellInfo const *spellInfo, bool state)
Definition: Unit.cpp:15189
bool IsAtStay()
Definition: Unit.cpp:19419
bool _isFollowing
Definition: Unit.h:1294
bool _isCommandAttack
Definition: Unit.h:1291
void GetStayPosition(float &x, float &y, float &z)
Definition: Unit.cpp:19395
ReactStates _oldReactState
Definition: Unit.h:1289
void ToggleCreatureAutocast(SpellInfo const *spellInfo, bool apply)
Definition: Unit.cpp:15134
bool IsCommandFollow()
Definition: Unit.cpp:19367
void SetForcedTargetGUID(ObjectGuid guid=ObjectGuid::Empty)
Definition: Unit.h:1274
void InitEmptyActionBar(bool withAttack=true)
Definition: Unit.cpp:14987
void SetIsCommandAttack(bool val)
Definition: Unit.cpp:19352
bool _isReturning
Definition: Unit.h:1295
Unit * _unit
Definition: Unit.h:1282
uint32 _petnumber
Definition: Unit.h:1286
bool HasStayPosition()
Definition: Unit.cpp:19409
CharmSpellInfo _charmspells[4]
Definition: Unit.h:1284
MeleeHitOutcome hitOutCome
Definition: Unit.h:896
uint32 absorbed_damage
Definition: Unit.h:892
WeaponAttackType attackType
Definition: Unit.h:895
Definition: DBCStructure.h:713
uint32 ModelId
Definition: DBCStructure.h:715
float scale
Definition: DBCStructure.h:718
Definition: DBCStructure.h:747
float Scale
Definition: DBCStructure.h:752
float CollisionWidth
Definition: DBCStructure.h:762
float CollisionHeight
Definition: DBCStructure.h:763
bool isMounted
Definition: Player.h:368
Player * opponent
Definition: Player.h:364
time_t startTime
Definition: Player.h:366
Definition: DBCStructure.h:868
int32 reputationListID
Definition: DBCStructure.h:870
Definition: DBCStructure.h:900
bool IsHostileTo(FactionTemplateEntry const &entry) const
Definition: DBCStructure.h:929
uint32 faction
Definition: DBCStructure.h:902
bool IsHostileToPlayers() const
Definition: DBCStructure.h:942
bool IsNeutralToAll() const
Definition: DBCStructure.h:943
bool IsFriendlyTo(FactionTemplateEntry const &entry) const
Definition: DBCStructure.h:912
uint32 factionFlags
Definition: DBCStructure.h:903
uint32 SubClass
Definition: ItemTemplate.h:631
uint32 Entry
Definition: Map.h:164
LiquidStatus Status
Definition: Map.h:168
uint32 SpellId
Definition: LootMgr.h:313
bool empty() const
Definition: LootMgr.h:366
void clear()
Definition: LootMgr.h:342
void generateMoneyLoot(uint32 minAmount, uint32 maxAmount)
Definition: LootMgr.cpp:795
bool FillLoot(uint32 lootId, LootStore const &store, Player *lootOwner, bool personal, bool noEmptyError=false, uint16 lootMode=LOOT_MODE_DEFAULT, WorldObject *lootSource=nullptr)
Definition: LootMgr.cpp:546
struct MovementInfo::JumpInfo jump
uint16 flags2
Definition: Object.h:544
void RemoveMovementFlag(uint32 flag)
Definition: Object.h:597
uint32 fallTime
Definition: Object.h:571
struct MovementInfo::TransportInfo transport
float splineElevation
Definition: Object.h:585
bool HasMovementFlag(uint32 flag) const
Definition: Object.h:598
float pitch
Definition: Object.h:568
float GetExactDist2d(const float x, const float y) const
Definition: Object.h:380
std::string ToString() const
Definition: Object.cpp:1026
float GetPositionZ() const
Definition: Object.h:336
float GetOrientation() const
Definition: Object.h:337
bool HasInArc(float arcangle, const Position *pos, float targetRadius=0.0f) const
Definition: Object.cpp:1599
bool IsPositionValid() const
Definition: Object.cpp:1787
void GetSinCos(float x, float y, float &vsin, float &vcos) const
Definition: Object.cpp:1551
void SetOrientation(float orientation)
Definition: Object.h:329
float GetPositionX() const
Definition: Object.h:334
void GetPosition(float &x, float &y) const
Definition: Object.h:339
float GetPositionY() const
Definition: Object.h:335
float GetAngle(const Position *pos) const
Definition: Object.cpp:1537
float GetExactDistSq(float x, float y, float z) const
Definition: Object.h:384
void Relocate(float x, float y)
Definition: Object.h:295
ProcTriggeredData(Aura *_aura)
Definition: Unit.cpp:15208
bool operator==(const uint32 spellId) const
Definition: Unit.cpp:15220
std::array< uint32, EFFECT_ALL > triggerSpelId
Definition: Unit.cpp:15218
SpellProcEventEntry const * spellProcEvent
Definition: Unit.cpp:15215
ObjectGuid GetTargetGUID() const
Definition: Unit.h:1081
Definition: SpellMgr.h:316
float ap_dot_bonus
Definition: SpellMgr.h:320
float dot_damage
Definition: SpellMgr.h:318
float ap_bonus
Definition: SpellMgr.h:319
float direct_damage
Definition: SpellMgr.h:317
SpellInfo const * last
Definition: SpellMgr.h:542
uint32 blockType
Definition: Unit.h:364
uint32 spellId
Definition: Unit.h:362
uint32 type
Definition: Unit.h:363
uint32 HitInfo
Definition: Unit.h:1053
Unit * attacker
Definition: Unit.h:1043
uint32 schoolMask
Definition: Unit.h:1047
SpellInfo const * spellInfo
Definition: Unit.h:1044
uint32 cleanDamage
Definition: Unit.h:1055
uint32 blocked
Definition: Unit.h:1052
AuraEffect const * auraEff
Definition: Unit.h:1063
Definition: SpellMgr.h:275
float ppmRate
Definition: SpellMgr.h:281
float customChance
Definition: SpellMgr.h:282
uint32 procFlags
Definition: SpellMgr.h:279
float maxRangeFriend
float minRangeFriend
float minRangeHostile
float maxRangeHostile
uint32 modelID_H
uint32 modelID_A
int32 creatureType
uint32 Type
void SetActionAndType(uint32 action, ActiveStates type)
Definition: Unit.h:1183
bool IsActionBarForSpell() const
Definition: Unit.h:1177
void SetType(ActiveStates type)
Definition: Unit.h:1188
void SetAction(uint32 action)
Definition: Unit.h:1193
uint32 GetAction() const
Definition: Unit.h:1176
uint32 m_ID
Definition: core.h:52
Definition: format.h:897